Making sure a field is always null in Django

牧云@^-^@ 提交于 2020-01-06 18:34:50

问题


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)

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!


回答1:


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:

  1. If all writes will come through default model forms:

    You can just set a default:

    class ThirdSubclass(ParentClass):
        foo = models.PositiveSmallIntegerField(blank=True, null=True, default=None, editable=False)
    
  2. If all writes will come through the use of model validation (that is, calling full_clean() before save()):

    You can use a validator:

    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. If all writes will come through the model:

    You can override save().

    class ThirdSubclass(ParentClass):
        def save(self, *args, **kwargs):
            if self.foo is not None:
                raise ValueError("...")
            super().save(*args, **kwargs)
    
  4. If writes can come from anywhere (for example, using update() or raw SQL):

    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.

Of these I would consider 2 to be standard, and the most elegant if you don't need the protections of 3 and 4.



来源:https://stackoverflow.com/questions/52914154/making-sure-a-field-is-always-null-in-django

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!