6

我正在使用启用了 mysql 和时区的 django 1.4.1。我向 yaml 做了一个转储数据,修改了一些字段以创建一些测试数据,并试图将其重新加载。然而,即使指定了 tz,Django 仍然抱怨天真的日期时间

具体来说,我的 loaddata 有:

fields: {created_date: !!timestamp '2012-09-15 22:17:44+00:00', ...

但 loaddata 给出了错误:

RuntimeWarning: DateTimeField received a naive datetime (2012-09-15 22:17:44) while time zone support is active.

这对我来说没有多大意义,因为它:

  1. UTC 时间戳
  2. Django 使用 dumpdata 导出的完全相同的格式

有什么方法可以告诉 django 这是一个 UTC 日期吗?

4

4 回答 4

22

问题源于 PyYAML。当 loaddata 将 datetime 交给 PyYAML 时,它会采用感知 datetime,将时间调整为 UTC,然后返回一个 naive datetime,它会生成警告。

有一张Django 票,以及一张关于该问题的PyYAML 票。两者都对上述意外行为进行了更详细的介绍。从门票中的评论来看,这个问题似乎不太可能很快得到解决。

您是否TIME_ZONE = 'UTC'在项目的 settings.py 中进行了设置,您将在正确的时间加载,但您仍然会收到警告。如果您的时区设置为其他任何时间,Django 会将日期时间视为本地时间,并将其调整为 UTC,这可能是不希望的。

避免这种情况的最好方法是使用 JSON 作为序列化格式。

希望有帮助。

于 2012-12-04T20:28:29.000 回答
9

文档...

序列化感知日期时间时,包括 UTC 偏移量,如下所示:

"2011-09-01T13:20:30+03:00"

对于一个天真的日期时间,它显然不是:

"2011-09-01T13:20:30"

......所以而不是......

created_date: !!timestamp '2012-09-15 22:17:44+00:00'

...任何一个...

created_date: '2012-09-15T22:17:44+00:00'

...或者...

created_date: '2012-09-15T22:17:44Z'

...将工作。

于 2012-11-15T18:35:32.103 回答
2

您可以将 django/core/serializers/pyyaml.py 复制到您的项目目录中,并替换以下代码(对于 ver.1.9.9 可能是 78-79 行)

for obj in PythonDeserializer(yaml.load(stream, Loader=SafeLoader), **options):
    yield obj

output = yaml.load(stream, Loader=SafeLoader)
for a_model in output:
    for key, value in a_model.items():
        if key == 'fields':
            for vkey, vvalue in value.items():
                if isinstance(vvalue, datetime.datetime):
                    value[vkey] = vvalue.replace(tzinfo=pytz.utc)
for obj in PythonDeserializer(output, **options):
    yield obj

当然 pytz 已经安装并且

import pytz

是需要的。

此代码会将所有原始日期时间值转换为 UTC 感知。

要覆盖默认序列化程序,请在 settings.py 中添加 SERIALIZATION_MODULES:

SERIALIZATION_MODULES = {'yaml': 'yourproj.pyyaml'}

我希望这个猴子补丁能正常工作。

于 2016-09-08T13:43:46.400 回答
0

我想继续使用 YAML 而不是 JSON 固定装置,以便我可以在数据中添加评论。这里的解决方法为我解决了这个问题:https ://code.djangoproject.com/ticket/18867

即,手动更改 YAML 夹具,使其:

  • 不使用 !!timestamp YAML 标签
  • 用引号将时间戳值括起来
  • 在时间戳值中包含时区信息

...显然这会触发 Django 的时间戳解析逻辑,而不是损坏的 PyYAML 逻辑。

于 2019-01-08T19:49:21.120 回答