【问题标题】:Post empty date field error with Django rest framework使用 Django 休息框架发布空日期字段错误
【发布时间】:2018-04-02 22:05:42
【问题描述】:

模型.py

class Form(models.Model):
    no = models.IntegerField()
    finish_date = models.DateField(blank=True, null=True)

序列化器.py

class FormSerializer(serializers.ModelSerializer):
    class Meta:
        model = Form
        fields = '__all__'

如果我尝试:

http http://127.0.0.1:8000/api/forms no=112 "finish_date"=""

返回错误:

"finish_date": [
    "Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]]."
]

如果我将 "finish_date" 设置为 null ,则此帖子有效。 而StringField(blank=True, null=True) 则不会报错。

如何解决?

【问题讨论】:

  • 你能发布你正在使用的序列化程序吗?

标签: django django-rest-framework


【解决方案1】:

现在在上述模型中,您有一个 DateField,并且 DateField 接受某些格式,类似于您帖子中错误中显示的格式。当您发布时:

http http://127.0.0.1:8000/api/forms no=112 "finish_date"=""

您实际上是在将一个空字符串 ("") 传递给序列化程序,这对于 DateField 来说不是有效的格式。而是在不传递“finish_date”参数的情况下尝试发布,我认为它会起作用。或者你可以在过去传递一些默认日期,而不是传递一个空字符串。

【讨论】:

  • 如何处理序列化程序本身的默认空白字符串,在进入验证之前出现错误,我可以在其中覆盖模型级别验证???
  • 知道为什么 Django 在 null=True, blank=True 时不接受空字符串吗?当 null=True 和 blank=True 时,大多数其他字段都接受空。
  • @SandeepBalagopal,大多数字段(如 char、text)都接受空,因为 '' 实际上是一个有效的字符串。现在,当我们在模型中使用组合 null=True、blank=True 并且不提供任何值时,db 会为字段存储 null(除了 char 和 text 字段,其中存储了 '')。现在空字符串不是有效的日期格式。因此,当我们在发布时没有指定 date_field 的 key('finish_date') 时,db 将其存储为 null。如需更多说明,请参阅:stackoverflow.com/a/8609425/8482471
  • @ShihabudheenKM,您发布的查询实际上是一个频繁的查询。现在处理当前情况的最佳方法是在发布请求中传递默认值或不提及 date_field 键或将值传递为 null,我认为上面已经提到过。现在对于您的问题,也许我们可以尝试此处提到的方法:stackoverflow.com/a/46910040/8482471。但是如果你问我,我认为最好不要管这个方法,也许因为这是一个例外情况,也许只是在视图本身中这样做。这样它看起来会更干净。只是我的想法。
  • 最好的办法是清理数据,使'' 变为null,因为serializers.DateField 还不支持allow_blank。这可以在提交之前完成,也可以由.to_internal_value() 方法中的序列化程序完成。
【解决方案2】:

如果有人对此问题有疑问并使用 javascript 客户端发布数据,请尝试将 undefined 作为空白日期发送

【讨论】:

  • 对我不起作用。它不会失败,但不会删除旧日期,而是将旧日期保留在数据库中。
【解决方案3】:

问题在于DateTimeField 目前不支持allow_blank 关键字参数。

不过它确实支持allow_null,所以你有两个选择:

  1. 发送前清理数据

清理"finish_date": "" -> "finish_date": null *发送到您的服务器之前

如果您使用 JavaScript 提交表单,您可能会执行以下操作:

if (data["finish_date"] == "") {
    data["finish_date"] = null;
}
  1. 接收后清理数据

在您的序列化程序中擦洗"finish_date": "" -> "finish_date": None

您可以使用ModelSerializer 上的.to_internal_value() 方法轻松完成此操作

class FormSerializer(serializers.ModelSerializer):
    class Meta:
        model = Form
        fields = '__all__'

    def to_internal_value(self, data):
        # check for "finish_date": "" and convert to None
        # This must be done before .validate()
        if data['finish_date'] == '':
            data['finish_date'] = None
        return super(FormSerializer, self).to_internal_value(data)

.to_internal_value()方法在Django Rest Framework Fields API Reference中被提及很多

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    相关资源
    最近更新 更多