Django 模型约束条件使用继承的字段 Class - 可能吗?

Django Model Constraint Condition Using Field From Inherited Class - Is It Possible?

我想使用来自父项 class 的字段作为子项 class 的约束条件。

models.py

class ParentClass(object):
    ...
    is_public = models.BooleanField(default=False)


class ChildClass(ParentClass):
    ...
    price = models.DecimalField(max_digits=6, decimal_places=2, null=True)
    class Meta:
        constraints = [
            models.CheckConstraint(
                check=Q(price__isnull=True) & Q(is_public=True), # <- here
                name='price_exists_check',
            )
        ]

当我尝试迁移时,我在终端中看到此错误:

myapp.ChildClass: (models.E016) 'constraints' refers to field 'is_public'
  which is not local to model 'ChildClass'.
  HINT: This issue may be caused by multi-table inheritance.

我看到此错误的原因很明显(is_public 字段位于 ParentClass 中)。我的问题是,那是不可能的,还是我可以重构一些东西?

我的最终目标是什么?

如果 pricenull,则不要让 ChildClass is_pulic 的实例更改为 True。我想在数据库级别强制执行此操作。

有没有办法,如果有,需要改变什么?

My question is, is it simply not possible then, or can I refactor something?

我查到的original commit which introduced the error message you're seeing, and the bug it was fixing. The documentation on model inheritance也有助于理解这个

我是这样理解这个问题的:

如果您创建一个继承自另一个模型的 Django 模型,并且该模型不是抽象的,那么 Django 会创建 parent table 的外键,而不是重复所有字段来自 child table 中的 parent 模型。因此,当您创建一个 ChildClass object 时,会在 ChildClass table ParentClass table.

中创建一行

您不能创建引用多个 table 的 CHECK 约束。 (据我所知。)因此,Django 禁止您创建此约束。

因此,您有以下选择:

  1. 在ORM层强制执行。在 clean() 方法中,检查您的约束是否得到满足。 (Documentation。)如果 non-Django 程序修改数据库,这不会阻止违反约束。

  2. 将 parent class 抽象化。你已经说过这行不通了。

  3. 创建第三个 class,它们都继承自 。像这样创建一个基础 class:

                -------------
                | BaseClass |
                -------------
                |           |
                V           V
    ---------------       --------------
    | ParentClass |       | ChildClass |
    ---------------       --------------
    

    将BaseClass抽象化,ParentClass和ChildClass具体化。这允许您使用约束,因为 ChildClass 数据现在只在一个 table 内。