How to implement a generalized uniqueness DB constraint (A,B) and (B,A) in Django?

73 views Asked by At

I want to check the database before an object is created with fields one='a' and two='b', and not create (throw an exception) if the database already has rows with fields one='b' and two='a' (reverse order). That is, guarantee that only one of (one, two) and (two, one) exists. It's like a generalized uniqueness constraint.

I'm using Django 3.2.

I see CheckConstraint supports a boolean Expression, and one type of expression is an aggregate. So I can imagine testing that the number of rows with (one, two) and (two, one) is at most 1. However, that sounds expensive, and I also don't see examples of how to use a Count in the CheckConstraint.

Alternatively, I could implement a pre_save signal that issues a query. This seems better, as I'll have the data in hand to form the query. However, I don't see how to prevent the save using the pre_save signal. Does it have a return value I can use? I don't see that in the docs.

EDIT: A third alternative might be overriding save to do the check.

I'm open to other ideas as well.

1

There are 1 answers

1
psolomon On

I cannot think of any database-level constraints that would allow this type of constraint.

So the constraint could be implemented at the application level. Are you creating the model when a form is submitted? In that case, you could check for an existing row in the database in the form validation code.