I'd like to use Django's CheckConstraint
to add a check
constraint to a table using PostgreSQLs num_nonnulls()
function, similar to this:
create table foo(
a text,
b int,
[...],
check num_nonnulls(a, b, ...) = n);
n
is a constant but may be different for different tables (mostly it's going to be 1
but I'd like to find a general solution). This is how far I got:
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')]
This is of course missing the step where the result of num_nonnulls()
is compared to some constant integer. I tried defining a function to do this:
def equals(a, b):
return models.Func(a, b, template='%(expressions[0])s = %(expressions[1])s')
But this doesn't work because the template argument expressions
is (I think) a string (and %
-template strings don't have this syntax to extract parts of an argument, I think).
Where do I go from here?
I'd like to find a solution that allows me to use arbitrary expressions supported by the Django ORM and also compare these expressions with other expressions or constants using an equality or inequality relation (e.g. =
or <=
).