我有一个父类,将通过3个不同的模型进行扩展。可以说,父类有一个名为foo
的字段,并且其中一个子类的该字段必须始终为null。我该如何确保?目前,我正在使用null=True
和editable=False
约束。但是,如果在创建对象的过程中暴露了该字段,则可以通过Shell或API来避免这些问题。
class ThirdSubclass(ParentClass):
# Over-ridden field from abstract parent class
foo = models.PositiveSmallIntegerField(blank=True, null=True, editable=False)
我还使用了PositiveSmallIntegerField,因为我想为该字段分配尽可能少的空间。无论如何,我该怎么做?覆盖保存方法是唯一的选择吗?理想情况下,我会喜欢字段定义中的某些内容。谢谢!
答案 0 :(得分:2)
正确的方法取决于您期望模型的使用方式。为了提高鲁棒性,以下是四种可能的方法:
如果所有写入都将通过默认模型形式进行:
您可以设置默认值:
class ThirdSubclass(ParentClass):
foo = models.PositiveSmallIntegerField(blank=True, null=True, default=None, editable=False)
如果所有写操作都将通过使用模型验证来完成(即在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])
如果所有写入都将通过模型进行:
您可以覆盖save()
。
class ThirdSubclass(ParentClass):
def save(self, *args, **kwargs):
if self.foo is not None:
raise ValueError("...")
super().save(*args, **kwargs)
如果写入可以来自任何地方(例如,使用update()
或原始SQL):
您需要数据库级别的约束。 Django没有为此提供模型级别的支持,但是您可以通过编写自定义迁移并使用RunSQL
创建约束来创建一个。
在这些中,我认为2是标准的,如果您不需要3和4的保护,则是最优雅的。