【问题标题】:Making sure a field is always null in Django确保 Django 中的字段始终为空
【发布时间】:2018-10-21 10:05:46
【问题描述】:

我有一个由 3 个不同模型扩展的父类。父类有一个名为foo 的字段,可以说,对于其中一个子类,该字段必须始终为空。我怎样才能确保这一点?现在,我正在使用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,因为我想为这个字段分配尽可能少的空间。无论如何,我该怎么做?覆盖保存方法是唯一的选择吗?理想情况下,我会喜欢字段定义中的某些内容。谢谢!

【问题讨论】:

  • 我怀疑您是否可以通过字段定义来实现这一点 - 但覆盖 model.save() 应该可以正常工作。

标签: django django-models


【解决方案1】:

执行此操作的正确方法取决于您希望如何使用模型。以下是四种可能的方法,以提高稳健性的顺序:

  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 的保护,则最优雅。

【讨论】:

  • 这是一个很好的答案。我想到了另一种解决方案。基本上,使用._meta.get_field('foo').get_internal_type()检查父类save()方法中foo字段的字段类型,如果是PositiveIntegerField,则再次手动设置为null。这样,只要字段类型为 PositiveIntegerField,它将始终为 null。很想听听您对此的看法。
  • @TahmidKhanNafee:这在功能上似乎等同于覆盖ThirdSubclass.save(),但远没有那么优雅。使用继承的全部意义在于将专门的行为放在子类上,而不是切换类型。
  • 是的,但是如果有 12 个以上的子类需要 foo 始终为空怎么办?覆盖这么多类不是问题吗?
  • @TahmidKhanNafee:如果是这种情况,那么您将创建一个新的中间类来实现该行为并让 12 岁以上的人从中继承。基于类的继承并不是解决所有代码重用问题的灵丹妙药,但如果你要使用 Django 的模型继承,你应该坚持使用范式。
猜你喜欢
  • 2021-07-18
  • 2020-07-19
  • 1970-01-01
  • 1970-01-01
  • 2015-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多