I want to create only one object for the same users.
class MyModel(models.Model):
user1 = models.ForeignKey(settings.AUTH_USER_MODEL,...)
user2 = models.ForeignKey(settings.AUTH_USER_MODEL,...)
class Meta:
constraints = [
UniqueConstraint(
fields=['user1', 'user2'],
name='user_unique',
),
# UniqueConstraint(
# fields=['user2', 'user1'],
# name='user_unique2',
# ),
]
I can solve the problem in another way, I just want to know how to do it with UniqueConstraint
.
Adding another UniqueConstraint and moving the fields didn't solve the problem.
For example, for users X and Y, I only need one object.
CodePudding user response:
Add a constraint that user1_id
should be less than user2_id
. In that case if you construct a MyModel
, for x
and y
, user1
will always take the user with the smallest primary key and vice versa:
class MyModel(models.Model):
user1 = models.ForeignKey(settings.AUTH_USER_MODEL, …)
user2 = models.ForeignKey(settings.AUTH_USER_MODEL, …)
class Meta:
constraints = [
UniqueConstraint(
fields=['user1', 'user2'],
name='user_unique',
),
CheckConstraint(
check=Q(user1_id__lt=F('user2_id')),
name='asymetric_users',
),
]
CodePudding user response:
Since Django 4.0 constraints now support expressions, this allows us to use database functions in our constraints allowing us to create a unique constraint with sorted fields:
from django.db.models.functions import Least, Greatest
class MyModel(models.Model):
user1 = models.ForeignKey(settings.AUTH_USER_MODEL,...)
user2 = models.ForeignKey(settings.AUTH_USER_MODEL,...)
class Meta:
constraints = [
UniqueConstraint(
Least("user1", "user2"), Greatest("user1", "user2"),
name='user_unique',
)
]
CodePudding user response:
There is a simple solution for you called unique_together which does exactly what you want.
Example:
class MyModel(models.Model):
field1 = models.CharField(max_length=50)
field2 = models.CharField(max_length=50)
class Meta:
unique_together = ('field1', 'field2',)
In your case:
class MyModel(models.Model):
user1 = models.ForeignKey(settings.AUTH_USER_MODEL,...)
user2 = models.ForeignKey(settings.AUTH_USER_MODEL,...)
class Meta:
unique_together = ('user1','user2',)