【问题标题】:RuntimeWarning: DateTimeField received a naive datetimeRuntimeWarning:DateTimeField 收到一个天真的日期时间
【发布时间】:2013-09-08 10:37:24
【问题描述】:

我正在尝试使用 IPython 发送一封简单的邮件。我没有设置任何仍然出现此错误的模型。可以做什么?

错误: /home/sourabh/Django/learn/local/lib/python2.7/site-packages/django/db/models/fields/init.py:827:RuntimeWarning:DateTimeField 收到一个幼稚的日期时间( 2013-09-04 14:14:13.698105) 时区支持处于活动状态。 运行时警告)

已尝试:第一步是将USE_TZ = True 添加到您的设置文件并安装pytz(如果可能)。

错误改变:

(learn)sourabh@sL:~/Django/learn/event$ python manage.py shell
/home/sourabh/Django/learn/local/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py:53: RuntimeWarning: SQLite received a naive datetime (2013-09-05 00:59:32.181872) while time zone support is active.
  RuntimeWarning)

【问题讨论】:

    标签: django django-mailer


    【解决方案1】:

    问题不在于 Django 设置,而在于传递给模型的 日期。以下是时区感知对象的外观:

    >>> from django.utils import timezone
    >>> import pytz
    >>> timezone.now()
    datetime.datetime(2013, 11, 20, 20, 8, 7, 127325, tzinfo=pytz.UTC)
    

    这是一个幼稚的对象:

    >>> from datetime import datetime
    >>> datetime.now()
    datetime.datetime(2013, 11, 20, 20, 9, 26, 423063)
    

    因此,如果您要在任何地方传递电子邮件日期(最终到达某个模型),只需使用 Django 的 now()。如果不是,则可能是现有软件包的问题,​​它获取没有时区的日期,您可以修补软件包、忽略警告或将 USE_TZ 设置为 False。

    【讨论】:

    • 你写tzinfo=<UTC>的地方,<UTC>是什么?这不是我见过的句法结构。
    • 聚会有点晚了,但您看到的是来自 shell 的 输出。更具体地说,它是 datetime 对象的 repr 方法的输出,它返回对象的可打印信息。
    • 在您使用datetime.now的地方,将其更改为timezone.now,并在顶部添加from django.utils import timezone
    • 对于那些仍在寻找 部分的人,您可以使用:import pytzdatetime.datetime(2013, 11, 20, 20, 8, 7, 127325, tzinfo=pytz.UTC)
    • 我的设置是USE_TZ = TrueTIME_ZONE = 'UTC'。但是当我使用timezone.now() 时,它不会显示tzinfo=<UTC>....所以这个日期时间对象被作为幼稚的对象传递。为什么会这样?
    【解决方案2】:

    使用django.utils.timezone.make_aware 函数让您的天真日期时间对象了解时区并避免这些警告。

    它将天真的日期时间对象(没有时区信息)转换为具有时区信息的对象(如果您没有将其明确指定为第二个参数,则使用 django 设置中指定的时区):

    import datetime
    from django.conf import settings
    from django.utils.timezone import make_aware
    
    naive_datetime = datetime.datetime.now()
    naive_datetime.tzinfo  # None
    
    settings.TIME_ZONE  # 'UTC'
    aware_datetime = make_aware(naive_datetime)
    aware_datetime.tzinfo  # <UTC>
    

    【讨论】:

    • 感谢您的回答,这是最符合 django 的方式,可以将天真的日期转换为具有我的 django 设置时区的日期:)
    • 可以把这个放到models.py中吗?
    • @Florent 如果您默认使用 utc 时区,则无需更改模型中的任何内容,auto_nowauto_now_add 将适用于日期时间字段。如果您出于某种原因需要在模型中使用时区感知当前日期时间对象 - 使用 django.utils.timezone.now() 函数。
    【解决方案3】:

    只是为了修复设置当前时间的错误

    from django.utils import timezone
    import datetime
    
    datetime.datetime.now(tz=timezone.utc) # you can use this value
    

    【讨论】:

    • 对于 datetime.datetime(9999, 01, 01, tzinfo=timezone.utc)
    • IMO 这是最实用的解决方案
    • from django.utils import timezone timezone.now() #也可以
    【解决方案4】:

    可以修复警告使用settings.py中指定的时区,这可能与UTC不同。

    例如在我的 settings.py 我有:

    USE_TZ = True
    TIME_ZONE = 'Europe/Paris'
    

    这是一个解决方案;优点是str(mydate) 给出了正确的时间:

    >>> from datetime import datetime
    >>> from django.utils.timezone import get_current_timezone
    >>> mydate = datetime.now(tz=get_current_timezone())
    >>> mydate
    datetime.datetime(2019, 3, 10, 11, 16, 9, 184106, 
        tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)
    >>> str(mydate)
    '2019-03-10 11:16:09.184106+01:00'
    

    另一种等效方法是使用make_aware,请参阅 dmrz 帖子。

    【讨论】:

      【解决方案5】:

      又快又脏 - 关掉它:

      USE_TZ = False
      

      在你的settings.py

      【讨论】:

      【解决方案6】:

      如果您想在 django 中将天真的日期时间转换为带时区的日期时间,这是我的解决方案:

      >>> import datetime
      >>> from django.utils import timezone
      >>> t1 = datetime.datetime.strptime("2019-07-16 22:24:00", "%Y-%m-%d %H:%M:%S")
      >>> t1
          datetime.datetime(2019, 7, 16, 22, 24)
      >>> current_tz = timezone.get_current_timezone()
      >>> t2 = current_tz.localize(t1)
      >>> t2
          datetime.datetime(2019, 7, 16, 22, 24, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)
      >>>
      

      t1 是一个简单的日期时间,t2 是一个日期时间,在 django 的设置中带有时区。

      【讨论】:

        【解决方案7】:

        您还可以覆盖设置,这在测试中特别有用:

        from django.test import override_settings
        
        with override_settings(USE_TZ=False):
            # Insert your code that causes the warning here
            pass
        

        这将阻止您看到警告,同时您的代码中需要时区感知日期时间的任何内容都可能会给您带来问题。如果是这种情况,请参阅 kravietz 的回答。

        【讨论】:

          【解决方案8】:

          在模型中,不要传值:

          timezone.now()
          

          相反,去掉括号,然后传递:

          timezone.now
          

          如果您继续收到运行时错误警告,请考虑将模型字段从 DateTimeField 更改为 DateField。

          【讨论】:

            【解决方案9】:

            确保 settings.py 有 USE_TZ = True

            在你的 python 文件中:

            from django.utils import timezone
            
            timezone.now() # use its value in model field
            
            

            【讨论】:

              猜你喜欢
              • 2018-02-15
              • 1970-01-01
              • 2016-08-19
              • 2021-02-17
              • 2014-01-29
              • 1970-01-01
              • 2014-03-28
              • 2019-08-06
              相关资源
              最近更新 更多