Ограничение модели Django DM: uniqueConstraint или checkConstraint?

Я пытаюсь определить уникальное ограничение для моей модели БД. У меня есть 3 ограничения, с двумя проблем нет, а вот с третьим у меня голова кругом идет.

Итак, класс модели довольно прост; это модель запроса на подключение к социальной сети (между аккаунтами пользователей). Вот ограничения, которые я пытаюсь применить:

  1. Пользователь1 должен иметь только один запрос на соединение с пользователем2: UniqueConstraint работает нормально.
  2. Пользователь1 не должен иметь возможности послать запрос на подключение к Пользователю1 (т.е. самому себе): CheckConstraint работает нормально.
  3. Если 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 , 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',
            ),
        ]
Вернуться на верх