Django CheckConstraint:反向ForeignKey查找的元素不能为空

Posted

技术标签:

【中文标题】Django CheckConstraint:反向ForeignKey查找的元素不能为空【英文标题】:Django CheckConstraint: Elements of reverse ForeignKey lookup must not be empty 【发布时间】:2020-05-27 03:35:23 【问题描述】:

我有这些模型:

class Container(models.Model):
    ...
    class Meta:
        constraints = [
            models.CheckConstraint(
                 check=~Q(elements=None),
                 name='container_must_have_elements'
            ),
        ]

class Element(models.Model):
    container = models.ForeignKey(Container),
        related_name='elements',
        on_delete=models.CASCADE
    )

我想强制每个Container 对象必须至少有一个Element 通过外键关系引用它。

如您所见,我已经添加了一个检查约束。但是,Q 对象上的否定运算符 ~ 似乎是被禁止的。当我尝试应用生成的迁移时,我得到了django.db.utils.NotSupportedError: cannot use subquery in check constraint

没有否定运算符,约束似乎是有效的(它只是由于数据完整性错误而失败)。

是否有另一种方式可以表达此约束以使其受到CheckConstraint 的支持? (例如,有没有办法检查elements 的集合是否不为空?)

【问题讨论】:

请注意,此约束将产生一种循环依赖,因为您无法在没有元素的情况下创建Container,但要创建Element,您需要一个容器来引用。在我看来,有这个约束是没有意义的 是的,你是对的,但仍然可以满足约束:两个模型的对象必须在单个数据库事务中创建。 @PeterF 我不太确定这单笔交易。 Container仍然需要先插入db才能获得pk,然后才能插入Element。那么第一次插入不会引发错误,即您确定仅在事务结束时检查约束吗? 立即或仅在事务提交后强制执行约束都是可配置的:postgresql.org/docs/9.1/sql-set-constraints.html 以下是使用 SQL 的方法:***.com/questions/3880698/… 他们需要在 SQL 中定义一个函数。似乎仅使用 python 代码无法对其他表定义约束。 【参考方案1】:

我将通过总结问题的 cmets 来回答我自己的问题。

检查约束旨在检查表中的每一行是否存在条件,该条件仅考虑行本身,而不会为此连接其他表。

坚持使用 SQL,可以通过在 SQL 中定义一个函数并从约束中调用它来制定包括其他表的扩展约束。

Django 2.2 中引入的CheckConstraint 仅通过使用Q 对象支持表本身的条件。 development version of the documentation 表示除了Q 对象之外,还将支持布尔Expressions。 这在 Django 3.0 中尚不可用,但在未来的版本中。

【讨论】:

以上是关于Django CheckConstraint:反向ForeignKey查找的元素不能为空的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能使用引用 SQL 中其他列的 checkConstraint 将列添加到现有表

django之路由层

Django 啥是反向关系?

django 反向生成models.py

如何访问反向关系django的反向关系

Django之URL反向解析