I have the following code for 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)
I want to write a database constraint on the TagBinding
model using a new Django 2.2 syntax. This constraint should check that tag
and activity
fields of the TagBinding
model have the same user. What I've tried to do:
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')),
)
]
But this doesn't work because Django doesn't allow to use joins inside of the F
function. Also Subquery
with OuterRef
didn't work for me because models that were referenced in a query were not registered.
Is there any way I can implement this constraint using a new syntax without raw SQL?
It seems like some SQL backends don't support joins in constraints definition, so the question now: is it even possible to implement this behavior in the relational database?
To define a one to many relationship in Django models you use the ForeignKey data type on the model that has the many records (e.g. on the Item model).
Introduction to Django Foreign Key. A foreign key is a process through which the fields of one table can be used in another table flexibly. So, two different tables can be easily linked by means of the foreign key. This linking of the two tables can be easily achieved by means of foreign key processes.
UniqueConstraint. condition. A Q object that specifies the condition you want the constraint to enforce. For example: UniqueConstraint(fields=['user'], condition=Q(status='DRAFT'), name='unique_draft_user')
Django models operate by default on relational database systems (RDBMS) and support relationships. Django Follows the 3 model Relationships: 1- One-To-One Relationship. 2- One-To-Many Relationship. 3- Many-To-Many Relatiosnship.
In Postgres, there are two types of constraints (other than things like unique and foreign key constraints), CHECK CONSTRAINTS and EXCLUDE constraints.
Check constraints can only apply to a single row.
Exclusion constraints can only apply to a single table.
You will not be able to use either of these to enforce the constraint you want, which crosses table boundaries to ensure consistency.
What you could use instead are trigger-based constraints, that can perform other queries in order to validate the data.
For instance, you could have a BEFORE INSERT OR UPDATE trigger on the various tables that checks the users match. I have some similar code that runs on same self-relation tree code that ensures a parent and child both have the same "category" as one another.
In this case, it's going to be a bit trickier, because you would need some mechanism of preventing the check until all tables involved have been updated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With