Django 严格检查感知时间戳

Django strict checking for aware timestamps

在 Django 中,如果您有 USE_TZ = True 并将原始日期时间传递给数据库调用,它会记录错误:

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

但是,Django 会继续执行操作,使用 settings.TIME_ZONE。有没有办法做更严格的检查?是否有设置让 Django 引发异常而不是仅仅记录警告?

至少从 Django 3.1 开始,没有这样的选项。

例如,来自 DateTimeField 的 relevant code 的一部分如下:

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

您可以通过创建 DateTimeField 的子项 class 并覆盖方法 get_prep_valueto_python 以引发异常而不是记录警告来获得所需的行为。

Django 文档确实包含一种引发异常的方法,而不仅仅是收到警告(Django 4.0,尚未检查它存在了多长时间)。对我来说,这看起来好像你应该只在开发期间添加它,而不是用于生产部署。

” 最后,为了帮助您找到需要升级的代码,当您尝试将原始日期时间保存到数据库时,Django 会发出警告: 在开发过程中,您可以将此类警告转换为异常并通过将以下内容添加到您的设置文件来获得回溯:

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