66 lines
2.5 KiB
Python
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
|