DjangoModelFactory中的Datetime字段破坏了集成测试(2.1)

时间:2019-04-08 11:01:07

标签: django datetime integration-testing factory-boy

我想在DjangoModelFactory中添加一个“ expiry_date”字段,以匹配其相关模型。

这是我的实现:

models.py

def set_default_expiry_date():
    return timezone.now() + datetime.timedelta(days=7)

[...]

    expiry_date = models.DateTimeField(
            verbose_name=_('Expiry date'),
            default=set_default_expiry_date,
            validators=[validate_expiry_date]
    )

factories.py

class OfferFactory(factory.django.DjangoModelFactory):
[...]
    expiry_date = factory.LazyFunction(set_default_expiry_date)

test_views.py

def test_POST_error_messages(self):
    offer = factory.build(dict, FACTORY_CLASS=OfferFactory)
    offer['price'] = 9999
    offer['item_count'] = -123

    self.client.force_login(self.company_user)
    response = self.client.post(self.url, offer)

    self.assertEqual(2, len(response.context['form'].errors))
    self.assertTrue(
        'price' and 'item_count' in response.context['form'].errors
    )

此测试应仅返回两个错误消息,均来自对“ price”和“ item_count”字段的验证约束失败。 但是我收到了翻译后的表格错误消息,说我应该提供有效的日期和时间。此错误消息并非源自我为此字段添加的自定义验证器。

为完整起见,这是表格的定义:

forms.py

class OfferForm(forms.ModelForm):
[...]
    class Meta:
        model = Offer
        fields = (
                [...]
                 'expiry_date'
        widgets = {
        [...]
                'expiry_date': forms.DateTimeInput(
                    attrs={'class': 'form-control', }
                )
        }

我已启用USE_TZUSE_L10N

看来datetime对象应该使用本地化格式,但不能这样做。

运行服务器时,datetime字段使用本地化格式。

因此,这不是表单级别的配置问题。

感谢您的见解,并感谢您的宝贵时间。

编辑:

输出 print(offer)

{'title': 'Back grow artist.', 'description': '...', 'price': 9999, 'item_count': -123, 'discount': 18, 'created_by': <CustomUser: TestCompany5>, 'expiry_date': datetime.datetime(2019, 4, 15, 13, 9, 52, 202191, tzinfo=<UTC>)}

2 个答案:

答案 0 :(得分:0)

In django, widgets are responsible for rendering the view. so you might expect that rendering a non-formatted DateTimeInput cause this unexpected behavior.

Try doing this:

class OfferForm(forms.ModelForm):
[...]
    class Meta:
        model = Offer
        fields = (
                [...]
                 'expiry_date'
        widgets = {
        [...]
                'expiry_date': forms.DateTimeInput(
                    attrs={'type': 'datetime-local', 
                           'class': 'form-control', },
                    format='your-desired-format'
                )
        }

Also add your desired format to your model field supported formats

input_formats = ['list-of-desired-formats']

For more details here: docs

答案 1 :(得分:0)

我最终决定使用其他方法,并简单地传递一个表示天数偏移量的整数。
感谢@Ramy Mohamed的见识。
我试图按原样发布datetime对象。由于小部件是作为文本输入呈现的,因此在POST请求之后,服务器将接收字符串,而不是日期时间对象。
我不需要配置他回答中所示的格式,因为他在谈论日期时间的显示方式,而不是反馈给服务器。

这就是我所做的工作:
test_views.py

locale_format = formats.get_format('DATETIME_INPUT_FORMATS', lang=translation.get_language())[0]
offer['expiry_date'] = offer['expiry_date'].strftime(locale_format)