Как использовать уникальное ограничение для одинаковых моделей
Я хочу создать только один объект для одних и тех же пользователей.
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',
# ),
]
Я могу решить проблему другим способом, я просто хочу знать, как это сделать с помощью UniqueConstraint
.
Добавление еще одного UniqueConstraint и перемещение полей не решило проблему.
Например, для пользователей X и Y мне нужен только один объект.
Добавьте ограничение, что user1_id
должен быть меньше user2_id
. В таком случае, если вы построите MyModel
, для x
и y
, user1
всегда будет брать пользователя с наименьшим первичным ключом, и наоборот:
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',
),
]
Для вас есть простое решение под названием unique_together, которое делает именно то, что вы хотите.
Пример:
class MyModel(models.Model):
field1 = models.CharField(max_length=50)
field2 = models.CharField(max_length=50)
class Meta:
unique_together = ('field1', 'field2',)
В вашем случае:
class MyModel(models.Model):
user1 = models.ForeignKey(settings.AUTH_USER_MODEL,...)
user2 = models.ForeignKey(settings.AUTH_USER_MODEL,...)
class Meta:
unique_together = ('user1','user2',)
Поскольку ограничения Django 4.0 теперь поддерживают выражения, это позволяет нам использовать функции базы данных в наших ограничениях, что позволяет нам создать уникальное ограничение с отсортированными полями:
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',
)
]