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
中)。我的问题是,那是不可能的,还是我可以重构一些东西?
我的最终目标是什么?
如果 price
是 null
,则不要让 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 禁止您创建此约束。
因此,您有以下选择:
在ORM层强制执行。在 clean() 方法中,检查您的约束是否得到满足。 (Documentation。)如果 non-Django 程序修改数据库,这不会阻止违反约束。
将 parent class 抽象化。你已经说过这行不通了。
创建第三个 class,它们都继承自 。像这样创建一个基础 class:
-------------
| BaseClass |
-------------
| |
V V
--------------- --------------
| ParentClass | | ChildClass |
--------------- --------------
将BaseClass抽象化,ParentClass和ChildClass具体化。这允许您使用约束,因为 ChildClass 数据现在只在一个 table 内。
我想使用来自父项 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
中)。我的问题是,那是不可能的,还是我可以重构一些东西?
我的最终目标是什么?
如果 price
是 null
,则不要让 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 禁止您创建此约束。
因此,您有以下选择:
在ORM层强制执行。在 clean() 方法中,检查您的约束是否得到满足。 (Documentation。)如果 non-Django 程序修改数据库,这不会阻止违反约束。
将 parent class 抽象化。你已经说过这行不通了。
创建第三个 class,它们都继承自 。像这样创建一个基础 class:
------------- | BaseClass | ------------- | | V V --------------- -------------- | ParentClass | | ChildClass | --------------- --------------
将BaseClass抽象化,ParentClass和ChildClass具体化。这允许您使用约束,因为 ChildClass 数据现在只在一个 table 内。