相关对象的Django模型约束

And*_*olf 10 python django django-models

我有以下模型代码:

class Tag(models.Model):
    user = models.ForeignKey('auth.User', on_delete=models.CASCADE)

class Activity(models.Model):
    user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    tags = models.ManyToManyField(Tag, through='TagBinding')

class TagBinding(models.Model):
    tag = models.ForeignKey(Tag)
    activity = models.ForeignKey(Activity)
Run Code Online (Sandbox Code Playgroud)

我想TagBinding使用新的Django 2.2语法在模型上编写数据库约束。此约束应检查tag和模型的activity字段TagBinding具有相同的用户。我尝试做的是:

class TagBinding(models.Model):
    tag = models.ForeignKey(Tag)
    activity = models.ForeignKey(Activity)

    class Meta:
        constraints = [
            models.CheckConstraint(
                name='user_equality',
                check=Q(tag__user=F('activity__user')),
            )
        ]
Run Code Online (Sandbox Code Playgroud)

但这是行不通的,因为Django不允许在F函数内部使用联接。也SubqueryOuterRef因为在查询中引用该模型没有注册也没有为我工作。

没有原始SQL,有什么方法可以使用新语法来实现此约束?

更新资料

似乎有些SQL后端不支持约束定义中的联接,所以现在的问题是:是否有可能在关系数据库中实现此行为?

Mat*_*kel 7

在 Postgres 中,有两种类型的约束(除了唯一和外键约束之外):CHECK CONSTRAINTS 和 EXCLUDE 约束。

检查约束只能应用于单行。

排除约束只能应用于单个表。

您将无法使用其中任何一个来强制执行您想要的约束,该约束会跨越表边界以确保一致性。

您可以使用基于触发器的约束,它可以执行其他查询以验证数据。

例如,您可以在各个表上使用 BEFORE INSERT OR UPDATE 触发器来检查用户是否匹配。我有一些类似的代码,在相同的自关系树代码上运行,确保父级和子级彼此具有相同的“类别”。

在这种情况下,这会有点棘手,因为您需要某种机制来阻止检查,直到更新所有涉及的表为止。