Как лучше всего сделать так, чтобы переменная сессии "django-timezone" устанавливалась на основе предпочтений профиля пользователя при каждом входе в систему?

Фон

Я прочитал этот раздел в документации Django под названием "Выбор текущего часового пояса", и мне стало ясно, как пользователь может выбрать предпочтительный часовой пояс для своей сессии (а затем промежуточное ПО убедится, что он будет использоваться в течение всей сессии):

  • разработчик готовит словарь часовых поясов для выбора пользователем
  • разработчик делает этот список доступным для пользователя в форме внутри шаблона, которая обслуживается GET запросом к представлению под названием set_timezone
  • пользователь выбирает часовой пояс с помощью этой формы и делает POST запрос
  • set_timezone представление использует простой однострочник для установки переменной "django-timezone" сессии: request.session["django_timezone"] = request.POST["timezone"]
  • Наконец, пользовательский класс TimezoneMiddleware, о котором говорится в документации, активирует часовой пояс для всех запросов представления в сессии с этого момента
  • .

Вопрос

Если я храню предпочтение часового пояса пользователя в модели User или модели профиля User, какой лучший способ сделать так, чтобы переменная "django-timezone" сессии всегда была установлена для всех его сессий (каждый раз, когда он входит в систему)?

Мысли/догадки

  • Нужно ли мне модифицировать встроенный в Django класс промежуточного ПО аутентификации?
  • Лучше всего будет расширить стандартный класс Django-стандарта LoginView из django.contrib.auth.views?
  • Или вышеупомянутый класс LoginView уже сам справится с этим, если я правильно настрою поле для хранения часового пояса в модели User? (или что-то вроде этого?)

Расширение LoginView

Как предложил Кевин Кристофер Генри в комментариях, я расширил встроенное представление входа в систему (решил поместить логику в метод form_valid()) после реализации того, что было предложено в документации Django под названием "Выбор текущего часового пояса". Я также покажу соответствующие части моей пользовательской модели, чтобы было понятно, как я храню предпочтения пользователей в отношении часовых поясов.

models.py

from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.validators import ASCIIUsernameValidator
# third-party package
from timezone_field import TimeZoneField

TZ_CHOICES = [
    (ZoneInfo('Pacific/Honolulu'), 'Pacific/Honolulu'),
    (ZoneInfo('America/Anchorage'), 'America/Anchorage'),
    (ZoneInfo('America/Los_Angeles'), 'America/Los_Angeles'),
    (ZoneInfo('US/Arizona'), 'US/Arizona'),
    (ZoneInfo('America/Denver'), 'America/Denver'),
    (ZoneInfo('America/Chicago'), 'America/Chicago'),
    (ZoneInfo('America/New_York'), 'America/New_York'),
]

class CustomUser(AbstractBaseUser, PermissionsMixin):
    username_validator = ASCIIUsernameValidator()

    """A bunch of fields (username, email, etc.)"""

    tz_preference = TimeZoneField(
        use_pytz=False, default="America/Denver", choices=TZ_CHOICES, choices_display="STANDARD", verbose_name=_('Timezone Preference')
    )

views.py

from django.contrib.auth.views import LoginView
from django.contrib.auth import login as auth_login
import zoneinfo
from django.utils import timezone

class CustomLoginView(LoginView):
    def form_valid(self, form):
        """Security check complete. Log the user in."""
        auth_login(self.request, form.get_user())
        # now set session timezone according to user's preference
        tzname = self.request.user.tz_preference.key
        self.request.session["django_timezone"] = tzname
        # and activate it (after this view, middleware will activate it)
        timezone.activate(zoneinfo.ZoneInfo(tzname))
        return HttpResponseRedirect(self.get_success_url())
Вернуться на верх