Files
NibasaViewer/NibasaViewer/middleware.py

66 lines
2.5 KiB
Python

from django.template.response import TemplateResponse
from django.core.exceptions import MultipleObjectsReturned
from viewer.models import UserSettings
class UserSettingsMiddleware:
"""Middleware that injects `theme` and `sort` into template response context.
On each request it looks for a UserSettings instance for the authenticated
user. The found values (or model defaults) are attached to the request and
then added to any TemplateResponse's context under the `theme` and `sort`
keys.
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Populate request attributes with user settings or defaults.
request.theme = None
request.sort = None
user = getattr(request, "user", None)
if user and getattr(user, "is_authenticated", False):
# Use filter().first() to avoid exceptions if no settings exist.
try:
settings_obj = UserSettings.objects.get(user=user)
except UserSettings.DoesNotExist:
settings_obj = UserSettings(user=user)
settings_obj.save()
except MultipleObjectsReturned:
settings_obj = UserSettings.objects.filter(user=user).first()
finally:
request.theme = settings_obj.theme
request.sort = settings_obj.sort
# Fall back to the model defaults when not set from DB.
if request.theme is None:
request.theme = UserSettings._meta.get_field("theme").get_default()
if request.sort is None:
request.sort = UserSettings._meta.get_field("sort").get_default()
response = self.get_response(request)
return response
def process_template_response(self, request, response):
"""Add `theme` and `sort` to TemplateResponse.context_data.
This method is only called for responses that implement
`render()` (TemplateResponse-like). We update or create
`context_data` so templates can access `theme` and `sort`.
"""
if not isinstance(response, TemplateResponse):
return response
ctx = getattr(response, "context_data", None)
if ctx is None:
response.context_data = {"theme": request.theme, "sort": request.sort}
else:
# Do not overwrite existing keys if templates or other processors set them
ctx.setdefault("theme", request.theme)
ctx.setdefault("sort", request.sort)
return response