There are 2 ways without and with django-tz-detect to automatically detect and apply the user's current timezone rather than applying only one timezone set to TIME_ZONE in settings.py
. *I recommend the way without django-tz-detect
and I use Django 4.2.3.
First, create middleware
folder with __init__.py
(Empty file) and custom.py
in core/
and copy base.html from django/contrib/admin/templates/admin/base.html
in your virtual environment to templates/admin/
as shown below. *You can see my answer explaining how to create middlewares and you can see my answer explaining how to set templates
folder and you can see my answer explaining how to override django admin templates:
django-project
|-core
| |-settings.py
| └-middleware # Here
| |-__init__.py
| └-custom.py
|-my_app1
|-my_app2
└-templates
|-my_app1
| └-base.html
|-my_app2
| └-base.html
└-admin
└-base.html # Here
<Without django-tz-detect
>
Now, put the code below to custom.py
:
# "core/middleware/custom.py"
import zoneinfo
from django.utils import timezone
from django.shortcuts import render
class TimezoneMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
tz = request.COOKIES.get("mytz")
if tz:
timezone.activate(zoneinfo.ZoneInfo(tz))
else:
timezone.activate(zoneinfo.ZoneInfo("UTC"))
return self.get_response(request)
Then, put <script></script>
just before </body>
in templates/my_app1/base.html
and templates/my_app2/base.html
as shown below:
{% "templates/my_app1/base.html" %}
{% "templates/my_app2/base.html" %}
<script>
let tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (!tz) {
tz = "UTC"
}
document.cookie = "mytz=" + tz + ";path=/";
</script>
</body>
Then, put <script></script>
just before </body>
tag in templates/admin/base.html
as shown below:
{% "templates/admin/base.html" %}
<script>
let tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (!tz) {
tz = "UTC"
}
document.cookie = "mytz=" + tz + ";path=/";
</script>
</body>
Finally, set TimezoneMiddleware
to MIDDLEWARE, then every time you load a django website, the user's current timezone is automatically detected and applied:
# "core/settings.py"
MIDDLEWARE = [
...
'core.middleware.custom.TimezoneMiddleware'
]
<With django-tz-detect
>
Now, install django-tz-detect
as shown below:
pip install django-tz-detect
Then, set tz_detect
and TimezoneMiddleware
to INSTALLED_APPS and MIDDLEWARE
respectively in settings.py
as shown below. *Make sure that django.template.context_processors.request is set to TEMPLATES's OPTIONS's context_processors
:
# "core/settings.py"
INSTALLED_APPS = [
...
'tz_detect' # Here
]
MIDDLEWARE = [
...
'tz_detect.middleware.TimezoneMiddleware', # Here
]
...
TEMPLATES = [
{
...
'DIRS': [
BASE_DIR / 'templates'
],
...
'OPTIONS': {
'context_processors': [
...
'django.template.context_processors.request', # Here
...
],
},
},
]
Then, add the path below to urlpatterns
in core/urls.py
as shown below:
# "core/urls.py"
urlpatterns = [
path('admin/', admin.site.urls),
path('my_app1/', include('my_app1.urls')),
path('my_app2/', include('my_app2.urls')),
path('tz_detect/', include('tz_detect.urls')) # Here
]
Then, load tz_detect.py
, then use tz_detect
tag just before </body>
tag in templates/my_app1/base.html
and templates/my_app2/base.html
as shown below:
{% "templates/my_app1/base.html" %}
{% "templates/my_app2/base.html" %}
{% load tz_detect %}
...
{% tz_detect %}
</body>
Finally, load tz_detect.py
, then use tz_detect
tag just before </body>
tag in templates/admin/base.html
as shown below:
{% "templates/admin/base.html" %}
{% ↓ Here ↓ %}
{% load i18n static i18n_switcher tz_detect %}<!DOCTYPE html>
...
<!-- END SVGs -->
{% tz_detect %}
</body>