Zags
Zags

Reputation: 41240

Django strict checking for aware timestamps

In Django, if you have USE_TZ = True and pass a naive datetime to a database call, it logs the error:

DateTimeField Model.field received a naive datetime (2021-01-01 00:00:00) while time zone support is active.

However, Django goes ahead and does the operation anyway, using settings.TIME_ZONE. Is there any way to do stricter checking? Is there a setting so that Django will raise an exception rather than just logging a warning?

Upvotes: 0

Views: 162

Answers (2)

voidnologo
voidnologo

Reputation: 1065

The Django docs do include a way to raise an exception instead of just getting a warning (Django 4.0, have not checked how long it has been there). For me this reads as though you should only add this during development, and not for production deploy.

" Finally, in order to help you locate code that needs upgrading, Django raises a warning when you attempt to save a naive datetime to the database: During development, you can turn such warnings into exceptions and get a traceback by adding the following to your settings file:

import warnings
warnings.filterwarnings(
    'error', r"DateTimeField .* received a naive datetime",
    RuntimeWarning, r'django\.db\.models\.fields',
)

"

https://docs.djangoproject.com/en/4.0/topics/i18n/timezones/#code

Upvotes: 1

Zags
Zags

Reputation: 41240

At least as of Django 3.1, there is no such option.

For example, one piece of relevant code from the DateTimeField is the following:

def get_prep_value(self, value):
    value = super().get_prep_value(value)
    value = self.to_python(value)
    if value is not None and settings.USE_TZ and timezone.is_naive(value):
        # For backwards compatibility, interpret naive datetimes in local
        # time. This won't work during DST change, but we can't do much
        # about it, so we let the exceptions percolate up the call stack.
        try:
            name = '%s.%s' % (self.model.__name__, self.name)
        except AttributeError:
            name = '(unbound)'
        warnings.warn("DateTimeField %s received a naive datetime (%s)"
                      " while time zone support is active." %
                      (name, value),
                      RuntimeWarning)
        default_timezone = timezone.get_default_timezone()
        value = timezone.make_aware(value, default_timezone)
    return value

You could get the desired behavior by creating a child class of the DateTimeField and overriding the methods get_prep_value and to_python to raise exceptions rather than log warnings.

Upvotes: 0

Related Questions