【问题标题】:Django 1.9 testing timezone.now() [duplicate]Django 1.9 测试 timezone.now() [重复]
【发布时间】:2016-07-08 15:16:22
【问题描述】:

TL;DR:仅从 timezone.now() 获取当前日期、当前小时和当前分钟,而不是秒和毫秒。

Django 版本:1.9 Python 版本:3.5.1

在测试我的应用模型时,我遇到了一个奇怪的(对我来说)错误。

我有这个模型:

import datetime

from django.core.urlresolvers   import reverse
from django.utils               import timezone
from django.db                  import models

class Muayene(models.Model):
    ...
    muayene_tarihi = models.DateField(
        default = timezone.now
    )
    ...

还有这个单元测试:

import datetime

from django.test                    import TestCase
from django.utils                   import timezone

from hasta.models                   import Hasta
from muayene.models                 import Muayene

class MuayeneModelTest(TestCase):

    fixtures = ['muayene_testdata', 'hasta_testdata']

    def setUp(self):
        Hasta.objects.create(ad="foo",soyad="bar",tc_kimlik_no="1234")
    def test_default_muayene_tarihi(self):
        hasta = Hasta.objects.get(ad="foo")
        muayene = Muayene.objects.create(hasta=hasta)
        self.assertEqual(muayene.muayene_tarihi, timezone.now())

测试输出:

FAIL: test_default_muayene_tarihi (muayene.tests.test_models.MuayeneModelTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/egegunes/Dropbox/Programs/hastatakip/muayene/tests/test_models.py", line 21, in test_default_muayene_tarihi
      self.assertEqual(muayene.muayene_tarihi, timezone.now())
      AssertionError: datetime.datetime(2016, 7, 8, 14, 38, 54, 780069, tzinfo=<UTC>) != datetime.datetime(2016, 7, 8, 14, 38, 54, 780539, tzinfo=<UTC>)

如您所见,问题在于从 models.py 调用的 timezone.now 和调用表单 test_models.pytimezone.now() 的输出之间的差异。

我找到了this question 的解决方法。但是存储确切的毫秒或秒并不是我的真正意图。我只想要当前日期和时间(小时和分钟)。此外,我不想设置default = datetime.date.today() 或类似的东西,因为 django 会发出关于仅使用timezone.now 的警告。

所以我的问题是,我如何才能使用timezone.now() 获取仅当前日期、小时和分钟?

【问题讨论】:

    标签: django unit-testing python-3.x django-models django-timezone


    【解决方案1】:

    由于您可以将任何可调用对象传递给default,因此只需编写您自己的函数即可。例如:

    from django.db import models
    from django.utils import timezone
    
    def strip_seconds(dt):
        return dt.replace(second=0, microsecond=0)
    
    def now():
        return strip_seconds(timezone.now())
    
    class Muayene(models.Model):
        # Note that this should be a DateTimeField, not a DateField
        muayene_tarihi = models.DateTimeField(default=now)
    

    因此,在您的测试中,您可以将now() 版本的返回值与数据库中的值进行比较(或在任意日期时间调用strip_seconds())。

    请注意,相等性比较仍然不完全可靠,因为如果两个调用碰巧跨越分钟边界,则可能会导致测试失败。

    【讨论】:

    • 那么,我是否遵循关于使用此函数和default=now 将默认值设置为timezone.now 的建议?
    • @egegunes:建议使用 Django 版本的 now() 而不是 Python 版本,因为它考虑了时区设置。我发布的代码就是这样做的。没有关于可调用 default 应该指向什么的建议。请参阅here,例如:“如果您需要不同的东西,您可能需要考虑简单地使用您自己的可调用默认值。”
    • 谢谢凯文,它似乎有效。
    猜你喜欢
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多