Hello hello!
In the django admin, I would like to annotate a row with a timezone-aware datetime.
Let’s imagine the following simplistic models:
class User(models.Model):
name = models.CharField()
class Event(models.Model):
user = models.ForeignKey(User)
type = models.PositiveIntegerField()
created_datetime = models.DateTimeField()
and in admin.py
:
from django.utils.timezone import make_aware
class UserAdmin(admin.ModelAdmin):
def event_datetime(self, obj):
return make_aware(obj.event_datetime)
event_datetime.admin_order_field = 'event_datetime'
def get_queryset(self, request):
qs = super(UserAdmin, self).get_queryset(request)
qs = qs.annotate(
event_datetime=Subquery(
Event.objects.filter(
user__pk=OuterRef('pk'),
type=123,
).order_by(
'-created_datetime'
).values_list(
'created_datetime',
flat=True
)[:1],
output_field=models.DateTimeField()
)
)
return qs
Now this works: the admin list view displays the list of users with a sortable “event datetime” column.
What is wrong is that the datetimes displayed are always (I think!) displayed in UTC format.
For example, the database value is (tripled-checked): 2022-10-10 09:19:38.729162
Rendered in the admin: Oct. 10, 2022, 9:19 a.m.
Should be: Oct. 10, 2022, 10:19 a.m.
A few things:
-
settings.TIMEZONE
is set toEurope/London
. -
→import pytz print(pytz.timezone(settings.TIME_ZONE).__dict__)
{'_tzinfos': {(datetime.timedelta(days=-1, seconds=86340), datetime.timedelta(0), 'LMT'): <DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD>, (datetime.timedelta(0), datetime.timedelta(0), 'GMT'): <DstTzInfo 'Europe/London' GMT0:00:00 STD>, (datetime.timedelta(seconds=3600), datetime.timedelta(seconds=3600), 'BST'): <DstTzInfo 'Europe/London' BST+1:00:00 DST>, (datetime.timedelta(seconds=7200), datetime.timedelta(seconds=7200), 'BDST'): <DstTzInfo 'Europe/London' BDST+2:00:00 DST>, (datetime.timedelta(seconds=3600), datetime.timedelta(0), 'BST'): <DstTzInfo 'Europe/London' BST+1:00:00 STD>}, '_utcoffset': datetime.timedelta(days=-1, seconds=86340), '_dst': datetime.timedelta(0), '_tzname': 'LMT'}
Thanks