Changing timezone per user in Django Admin

Home

Lets first have a background on storing and displaying timestamps:

Some things to keep in mind when converting timestamps from one timezone to another:

Starting from scratch, we create a new Django project:

django-admin startproject myproject
cd myproject

Then we install required packages in a virtual environment (install poetry):

poetry init -n
poetry add django django-timezone-field

Then we create a Django app:

poetry run python manage.py startapp custom_user

We then modify custom_user/models.py to add timezone field in our custom User model:

from django.db import models
from django.contrib.auth.models import AbstractUser
from timezone_field import TimeZoneField

class User(AbstractUser):
    timezone = TimeZoneField(default="Asia/Kolkata")

Now we register the User model in custom_user/admin.py so that we can edit user information like timezone, username, etc.

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin

from custom_user.models import User

@admin.register(User)
class CustomUserAdmin(UserAdmin):
    model = User

    def get_fieldsets(self, request, obj=None):
        fieldsets = super().get_fieldsets(request, obj)
        fieldsets[0][1]["fields"] += ("timezone",)
        return fieldsets

What we did was registering timezone information per user. Now, we need to intercept each request using Django’s middleware so that we can activate the timezone specific to the user currently logged in. For this we need to add the following in custom_user/middleware.py:

from django.utils import timezone

def set_timezone(get_response):
    def get_response_wrapper(request):
        if request.user.is_authenticated:
            timezone.activate(request.user.timezone)
        else:
            timezone.deactivate()
        return get_response(request)

    return get_response(request)

Next we register our app, middleware and user model in myproject/settings.py:

INSTALLED_APPS += ['custom_user']
MIDDLEWARE += ['custom_user.middleware.set_timezone']
AUTH_USER_MODEL = "custom_user.User"

Now we just need to migrate our changes to database and run the server:

poetry run python manage.py makemigrations
poetry run python manage.py migrate
poetry run python manage.py createsuperuser
poetry run python manage.py runserver