确保字段在Django中始终为null [英] Making sure a field is always null in Django
问题描述
我有一个父类,将通过3个不同的模型进行扩展。可以说,父类有一个名为 foo
的字段,并且对于子类之一,该字段必须始终为null。我该如何确保?现在,我正在使用 null = True
和 editable = False
约束。但是,如果在创建对象的过程中暴露了该字段,则可以从外壳程序或API中规避这些问题。
I have a parent class which is being extended by 3 different models. The parent class has a field called foo
lets say, and this field needs to be always null for one of the sub-classes. How can I ensure this? Right now, I am using null=True
, and editable=False
constraints. However, these can be circumvented from the shell or an API if the field is exposed during object creation.
class ThirdSubclass(ParentClass):
# Over-ridden field from abstract parent class
foo = models.PositiveSmallIntegerField(blank=True, null=True, editable=False)
我还使用了PositiveSmallIntegerField,因为我想为该字段分配尽可能少的空间。无论如何,我该怎么做?覆盖保存方法是唯一的选择吗?理想情况下,我会喜欢字段定义中的某些内容。谢谢!
I am also using the PositiveSmallIntegerField since I want to allocate as little space as possible for this field. Anyway, how do I do this? Is over-riding the save method the only option? Ideally, I would love something within the field definition. Thanks!
推荐答案
正确的方法取决于您期望模型的使用方式。以下是四种可能的方法,以提高健壮性的顺序:
The right way to do this depends on how you expect your models to be used. Here are four possible approaches, in order of increasing robustness:
-
如果所有写入都将通过默认模型形式进行:
If all writes will come through default model forms:
您可以设置默认值:
class ThirdSubclass(ParentClass):
foo = models.PositiveSmallIntegerField(blank=True, null=True, default=None, editable=False)
如果所有写入都将通过使用模型验证来完成(即调用 full_clean()
在 save()$ c之前$ c>):
您可以使用验证器:
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])
如果所有写入都会通过该模型:
If all writes will come through the model:
您可以覆盖 save()
。
class ThirdSubclass(ParentClass):
def save(self, *args, **kwargs):
if self.foo is not None:
raise ValueError("...")
super().save(*args, **kwargs)
如果写入可以来自任何地方(例如,使用 update()
或原始SQL):
If writes can come from anywhere (for example, using update()
or raw SQL):
您需要数据库级约束。 Django没有为此提供模型级别的支持,但是您可以通过编写自定义迁移并使用 RunSQL
创建约束来创建一个。
You need a database-level constraint. Django has no model-level support for this, but you could create one by writing a custom migration and using RunSQL
to create the constraint.
其中我认为2是标准的,如果您不需要3和4的保护,则是最优雅的。
Of these I would consider 2 to be standard, and the most elegant if you don't need the protections of 3 and 4.
这篇关于确保字段在Django中始终为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!