使用继承类中的字段的 Django 模型约束条件 - 可能吗?
Posted
技术标签:
【中文标题】使用继承类中的字段的 Django 模型约束条件 - 可能吗?【英文标题】:Django Model Constraint Condition Using Field From Inherited Class - Is It Possible? 【发布时间】:2021-12-07 15:36:33 【问题描述】:我想使用父类的字段作为子类的约束条件。
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
。我想在数据库级别执行此操作。
有没有办法,如果有,需要改变什么?
【问题讨论】:
将父类标记为抽象类有帮助吗?见***.com/a/36824386/530160 还是需要父类是具体类? 我确实需要父类是一个具体的类。 【参考方案1】:我的问题是,那是不可能的,还是我可以重构一些东西?
我找到了original commit,它介绍了您看到的错误消息,以及它正在修复的bug。 model inheritance 上的文档也有助于理解这一点。
我是这样理解这个问题的:
如果您创建一个从另一个模型继承的 Django 模型,并且该模型不是抽象的,那么 Django 会为父表创建一个外键,而不是在子表中重复父模型中的所有字段。因此,当您创建 ChildClass 对象时,会在 ChildClass 表和 ParentClass 表中创建一行。
您不能创建引用多个表的 CHECK 约束。 (据我所知。)因此,Django 禁止您创建此约束。
因此,您有以下选择:
在 ORM 层强制执行。在 clean() 方法中,检查您的约束是否满足。 (Documentation.) 如果非 Django 程序修改数据库,这不会防止违反约束。
使父类抽象。你已经说过这是行不通的。
创建第三个类,它们都继承自。像这样创建一个基类:
-------------
| BaseClass |
-------------
| |
V V
--------------- --------------
| ParentClass | | ChildClass |
--------------- --------------
将 BaseClass 抽象化,将 ParentClass 和 ChildClass 具体化。这允许您使用约束,因为 ChildClass 数据现在只在一个表中。
【讨论】:
以上是关于使用继承类中的字段的 Django 模型约束条件 - 可能吗?的主要内容,如果未能解决你的问题,请参考以下文章
约束 unique_together 可能与 django 类中的唯一字段冲突