Django DateTimeField 在时区支持处于活动状态时收到一个天真的日期时间

Django DateTimeField received a naive datetime while time zone support is active

我正在使用 Django 2.2

在我的应用程序中,时区支持由设置文件中的 USE_TZ=True 启用。

我有带有 DateTime 字段 created 的模型。

我需要根据日期过滤数据。日期可以由用户提供,否则将默认为 now().

这就是我正在做的

from datetime import datetime, timedelta
from django.utils import timezone

class Generator:

    def __init__(self, start_date=None, end_date=None):

        if end_date:
            self.end_date = datetime.strptime(end_date, '%Y-%m-%d').date()
        else:
            self.end_date = timezone.now().date()

        if start_date:
            self.start_date = datetime.strptime(start_date, '%Y-%m-%d').date()
        else:
            self.start_date = self.end_date - timedelta(days=7)

    def get_query(self, d):

        query = MyModel.objects.filter(
            d__in=d,
            created__gte=start_date,
            created__lte=end_date
        )

        return query

但是这是错误的

RuntimeWarning: DateTimeField MyModel.created received a naive datetime (2020-02-28 00:00:00) while time zone support is active.

如何解决这个问题?

如果 myday 是一个代表日期的字符串,为了不得到一个简单的日期时间,可以这样直接将它转换成日期:

from time import strptime

myday = date(*strptime(myday, "%Y-%m-%d")[:3])

此方法避免了必须从原始日期时间转换为感知日期时间。

您可以添加以下代码以确保 start_date 和 end_date 具有时区信息。 例如

tz = timezone.get_current_timezone()

start_date = start_date.replace(tzinfo=tz)
end_date = end_date.replace(tzinfo=tz)

启用时区支持后,数据库层预计只会从您的代码中接收可感知的日期时间。当它收到一个天真的日期时间时会出现此警告。这表明您尚未完成时区支持代码的移植。检查 documentation.

您需要使用 make_aware() 函数将原始日期时间更改为您的项目时区日期时间。为此,您必须像下面这样更新您的代码。

from datetime import datetime, timedelta
from django.utils import timezone

class Generator:

    def get_mytimezone_date(original_datetime):
        new_datetime = datetime.strptime(original_datetime, '%Y-%m-%d')
        tz = timezone.get_current_timezone()
        timzone_datetime = timezone.make_aware(new_datetime, tz, True)
        return timzone_datetime.date()

    def __init__(self, start_date=None, end_date=None):

        if end_date:
            self.end_date = self.get_mytimezone_date(end_date)
        else:
            self.end_date = timezone.now().date()

        if start_date:
            self.start_date = self.get_mytimezone_date(start_date)
        else:
            self.start_date = self.end_date - timedelta(days=7)

    def get_query(self, d):

        query = MyModel.objects.filter(
            d__in=d,
            created__gte=start_date,
            created__lte=end_date
        )

        return query

希望对您有所帮助:)