Ограничение модели Django DM: uniqueConstraint или checkConstraint?
Я пытаюсь определить уникальное ограничение для моей модели БД. У меня есть 3 ограничения, с двумя проблем нет, а вот с третьим у меня голова кругом идет.
Итак, класс модели довольно прост; это модель запроса на подключение к социальной сети (между аккаунтами пользователей). Вот ограничения, которые я пытаюсь применить:
- Пользователь1 должен иметь только один запрос на соединение с пользователем2: UniqueConstraint работает нормально.
- Пользователь1 не должен иметь возможности послать запрос на подключение к Пользователю1 (т.е. самому себе): CheckConstraint работает нормально.
- Если User1 посылает запрос на соединение User2, то User2 не должен иметь возможности послать запрос на соединение обратно User1: вот с этим я и мучаюсь.
Как я могу применить 3-е ограничение здесь? Я сначала думал, что 1-е ограничение обеспечивает обратное ограничение (где уникальность двух записей в таблице обеспечивается независимо от порядка), но это не похоже на то (и имеет смысл).
class ConnectionRequest(models.Model):
senderAccount = models.ForeignKey(
Account, related_name='sender_Account', on_delete=models.CASCADE)
recipientAccount = models.ForeignKey(
Account, related_name='recipient_Account', on_delete=models.CASCADE)
requested = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.senderAccount.id) + ' to ' + str(self.recipientAccount.id)
class Meta:
constraints = [
# duplicate connection request constraint
models.UniqueConstraint(name='duplicate_connreq_constraint',
fields=['senderAccount', 'recipientAccount']),
# self connection request constraint
models.CheckConstraint(name='self_connection_request_constraint',
check=~models.Q(
senderAccount=models.F("recipientAccount")),
),
]
Since django-4. 0, you could make a functional unique constraint with the Least
[Django-doc] and Greatest
[Django-doc] of the two, so:
from django.db.models.functions import Least, Greatest
class ConnectionRequest(models.Model):
senderAccount = models.ForeignKey(
Account, related_name='sender_Account', on_delete=models.CASCADE
)
recipientAccount = models.ForeignKey(
Account, related_name='recipient_Account', on_delete=models.CASCADE
)
requested = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.senderAccount_id} to {self.recipientAccount_id}'
class Meta:
constraints = [
models.UniqueConstraint(
name='duplicate_connreq_constraint',
fields=['senderAccount', 'recipientAccount'],
),
models.CheckConstraint(
name='self_connection_request_constraint',
check=~models.Q(senderAccount=models.F("recipientAccount")),
),
models.UniqueConstraint(
Least('senderAccount', 'recipientAccount'),
Greatest('senderAccount', 'recipientAccount'),
name='antisymmetric',
),
]