确保字段在Django中始终为null

时间:2018-10-21 10:05:46

标签: django django-models

我有一个父类,将通过3个不同的模型进行扩展。可以说,父类有一个名为foo的字段,并且其中一个子类的该字段必须始终为null。我该如何确保?目前,我正在使用null=Trueeditable=False约束。但是,如果在创建对象的过程中暴露了该字段,则可以通过Shell或API来避免这些问题。

class ThirdSubclass(ParentClass):
    # Over-ridden field from abstract parent class
    foo = models.PositiveSmallIntegerField(blank=True, null=True, editable=False)

我还使用了PositiveSmallIntegerField,因为我想为该字段分配尽可能少的空间。无论如何,我该怎么做?覆盖保存方法是唯一的选择吗?理想情况下,我会喜欢字段定义中的某些内容。谢谢!

1 个答案:

答案 0 :(得分:2)

正确的方法取决于您期望模型的使用方式。为了提高鲁棒性,以下是四种可能的方法:

  1. 如果所有写入都将通过默认模型形式进行:

    您可以设置默认值:

    class ThirdSubclass(ParentClass):
        foo = models.PositiveSmallIntegerField(blank=True, null=True, default=None, editable=False)
    
  2. 如果所有写操作都将通过使用模型验证来完成(即在save()之前调用full_clean()

    您可以使用验证器:

    def validate_none(value):
        if value is not None:
            raise ValidationError("...")
    
    class ThirdSubclass(ParentClass):
        foo = models.PositiveSmallIntegerField(blank=True, null=True, default=None, editable=False,
                                               validators=[validate_none])
    
  3. 如果所有写入都将通过模型进行:

    您可以覆盖save()

    class ThirdSubclass(ParentClass):
        def save(self, *args, **kwargs):
            if self.foo is not None:
                raise ValueError("...")
            super().save(*args, **kwargs)
    
  4. 如果写入可以来自任何地方(例如,使用update()或原始SQL):

    您需要数据库级别的约束。 Django没有为此提供模型级别的支持,但是您可以通过编写自定义迁移并使用RunSQL创建约束来创建一个。

在这些中,我认为2是标准的,如果您不需要3和4的保护,则是最优雅的。