1

我想使用父类中的字段作为子类中的约束条件。

模型.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)。我的问题是,那是不可能的,还是我可以重构一些东西?

我的最终目标是什么?

不让实例ChildClass is_pulic更改为Trueif the priceis null。我想在数据库级别强制执行此操作。

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

4

1 回答 1

1

我的问题是,那是不可能的,还是我可以重构一些东西?

我追踪了原始提交,它介绍了您看到的错误消息,以及它正在修复的错误。关于模型继承的文档也有助于理解这一点。

以下是我对这个问题的理解:

如果您创建一个从另一个模型继承的 Django 模型,并且该模型不是抽象的,那么 Django 会为父表创建一个外键,而不是在子表中重复父模型中的所有字段。因此,当您创建 ChildClass 对象时,会在 ChildClass 表ParentClass 表中创建一行。

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

因此,您有以下选择:

  1. 在 ORM 层强制执行它。在 clean() 方法中,检查您的约束是否满足。(文档。)如果非 Django 程序修改数据库,这不会防止违反约束。

  2. 使父类抽象。你已经说过这是行不通的。

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

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

    使 BaseClass 抽象,而 ParentClass 和 ChildClass 具体。这允许您使用约束,因为 ChildClass 数据现在仅在一个表中。

于 2021-10-20T20:55:10.020 回答