比较CHECK约束中与常量的表达式



我想使用Django的CheckConstraint添加check约束到使用postgresql的num_nonnulls()函数的表,类似于:

create table foo(
a text,
b int,
[...],
check num_nonnulls(a, b, ...) = n);

n是一个常数,但对于不同的表可能不同(主要是1,但我想找到一个通用的解决方案)。这是我得到的结果:

class Foo(models.Model):
a = models.TextField(null=True)
b = models.IntegerField(null=True)
[...]
class Meta:
constraints = [
models.CheckConstraint(
check=models.ExpressionWrapper(
models.Func('a', 'b', function='num_nonnulls'),
models.BooleanField()),
name='num_nonnulls_check')]

这当然错过了将num_nonnulls()的结果与某个常数整数进行比较的步骤。我尝试定义一个函数来做这个:

def equals(a, b):
return models.Func(a, b, template='%(expressions[0])s = %(expressions[1])s')

但这不起作用,因为模板参数expressions是(我认为)一个字符串(和%-模板字符串没有这种语法来提取参数的部分,我认为)。

我该往哪里走?

我想找到一个解决方案,允许我使用Django ORM支持的任意表达式,并使用相等或不相等关系(例如=<=)将这些表达式与其他表达式或常量进行比较。

从Django 4开始,这是可能的,参见下面的变更日志条目:

查找表达式现在可以在QuerySet注释、聚合中使用,也可以直接在过滤器中使用。

这应该适合你的例子。

from django.db import models
from django.db.models.constraints import CheckConstraint
from django.db.models.expressions import Func
from django.db.models import Value
from django.db.models.fields import IntegerField, TextField

class Foo(models.Model):
a = models.TextField(null=True)
b = models.IntegerField(null=True)
class Meta:
constraints = [
CheckConstraint(
name='num_nonnulls_check',
check=Exact(
lhs=Func('a', 'b', function='num_nonnulls', output_field=IntegerField()),
rhs=Value(1),
),
)
]

相关内容

  • 没有找到相关文章

最新更新