【问题标题】:DRF BooleanField in ModelSerializer causes IntegrityErrorModelSerializer 中的 DRF BooleanField 导致 IntegrityError
【发布时间】:2018-03-22 08:07:11
【问题描述】:

我的 ModelSerializer 遇到问题

class Recall(models.Model):
    thermal_step = models.BooleanField()
    have_inventory = models.BooleanField()
    have_adverse = models.BooleanField()


class OrderRecallSerializer(serializers.ModelSerializer):
    class Meta:
        model = Recall
        fields = ['thermal_step', 'have_inventory', 'have_adverse']

s = OrderRecallSerializer(data={})
s.is_valid()
>>> True
s.save()
>>> django.db.utils.IntegrityError: null value in column 
"thermal_step" violates not-null constraint

在 django 中,BooleanField 始终设置为 blank=True,因为浏览器不会在 POST 数据中发送未选中的复选框。

在这种情况下,ModelForm 将模型字段设置为 False。使用 DRF ModelSerializer 时,生成的 BooleanField 使用 required=False 创建,当数据中不存在该字段时,传递给序列化程序,模型字段设置为 None 并在保存模型时引发 IntegrityError。

我应该在我的 ModelSerializer 中明确指定 BooleanField(default=False),还是我遗漏了什么?我希望 ModelSerializer 的行为类似于 ModelForm - 当它不存在时将值设置为 False,这等于自动生成默认 = False 的 BooleanField。

我认为获得默认行为的 IntegrityError 不是预期的,也许我应该提交一个错误?

【问题讨论】:

  • 使用models.NullBooleanField()models.BooleanField(required=False, null=True, default=False)
  • @alfonso.kim 我不需要存储空值,我认为为 BooleanField 指定 null=True 是错误的想法。此外,models.BooleanField 的 required 参数是错误的。也许最好的答案是始终为 BooleanField 设置 default=False ...

标签: django django-rest-framework


【解决方案1】:

这是旧版本 Django Rest Framework https://github.com/encode/django-rest-framework/issues/1004 中的一个错误,但似乎前段时间已解决,可能您需要在序列化程序中明确使其成为必需,例如:

class OrderRecallSerializer(serializers.ModelSerializer):
    class Meta:
        model = Recall
        fields = ['thermal_step', 'have_inventory', 'have_adverse']
        extra_kwargs = {
          'thermal_step': {'required': True, 'allow_null': False},
          'have_inventory': {'required': True, 'allow_null': False},
          'have_adverse': {'required': True, 'allow_null': False},
        }

或者@bear-brown 所说的通常是最佳实践。

【讨论】:

    【解决方案2】:

    当您使用models.BooleanField 时,通常需要检查值是否为真,所以我认为最佳实践总是为其设置default 值。并在模型类中设置default,例如在您的情况下:

    class Recall(models.Model):
        thermal_step = models.BooleanField(default=False)
        have_inventory = models.BooleanField(default=False)
        have_adverse = models.BooleanField(default=True)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-09
      • 1970-01-01
      • 1970-01-01
      • 2015-11-12
      • 2015-04-04
      • 2020-04-01
      • 1970-01-01
      相关资源
      最近更新 更多