I wanted to finetune the date display in the admin.
I have a model with a DateTimeField defined as:
start_date = m.DateTimeField(blank=False, default=now) # start date
I have a property for that model defined as:
@property
def start_datetime(self):
return self.start_date.strftime("%d.%m.%Y %H:%M")
In the admin, I have list_display as:
list_display = ['start_date', 'start_datetime', ...]
The first column uses standard format and puts out the exact date and time. The second column will have everything correct except for the hours. They are most of the time off by one hour, but sometimes are off by two hours.
Here’s my settings concerning dates and time:
LANGUAGE_CODE = 'de-de'
TIME_ZONE = 'Europe/Berlin'
USE_I18N = True
USE_TZ = True
LOCALE_PATHS = (
BASE_DIR / 'locale',
)
Datetimes are stored in the database as UTC.
Datetimes are converted to local times by views or templates being rendered.
Your start_date field is going to render correctly, localized, because it is a datetime field being passed to the template.
However, the date returned by the start_datetime method is not going to be localized, because you’re returning a string to the template and not a datetime object.
Ok. That makes sense. So I should be fine if let my property return a datetime, right?
But why is the offset not always the same? 1 hour off makes sense. That is the difference between UTC and Berlin/Europe. But why is it sometimes 2 hours off?
My gut hunch would be a DST adjustment, but without seeing the data, I can only guess.
Hm… I just realized my solution won’t work. If I just pass a date to the template, it will be displayed in standard format. That is not what I want. I also don’t really want to overwrite the template. Is there a way to manually localize the date before I pass it on as a string?
Yes, but it depends.
Django attempts to render times based on the user’s time zone - which could be different from the default time zone you define in your settings.
You would need to decide which “local” time zone to use - your default or the user’s.
In either case, you should find the docs helpful, starting at:
As so often with the Django Admin: I’ll just use the default setting, as the effort to make a minor change is just exhausting.
Yep, because the admin has never been intended as a general purpose front-end.
Yeah. I find it really annoying. There’s a bunch of things in the admin that are really well done. Like the date pikcer for instance. But then you have to do it all over again when you want to use the same functionality, because they have weird hooks that make it impossible to just use them in your projects. Not very DRY.
I’m not sure I’d ever want to consider an internal and undocumented interface as something I’d want to use in my application. There’s always the chance that it gets changed in an update and never publicised.
<opinion>
DRY as an architectural principle is ok. But the real skill with using architectural principles is knowing when they don’t apply - and I draw that line with internal and undocumented interfaces.
If I considered that date picker to be so important as to want to use it in my projects, I’d extract it and make it a standalone module. I wouldn’t trust that it’s going to remain as a stable interface within Django itself, when, by its nature as an undocumented component, is subject to being changed or eliminated without notice or going through the deprecation cycle.
</opinion>