Индивидуальный подход в зависимости от состояния - PullRequest
1 голос
/ 05 мая 2020

У меня есть модель, которая выглядит так:

class Voting(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    choice = models.ForeignKey(Choice, on_delete=models.CASCADE)
    answered_at = models.DateTimeField(auto_now_add=True)

Она работает должным образом, однако пользователь не должен иметь возможность голосовать по одному и тому же вопросу дважды. Другими словами, пользователь не должен иметь возможность проголосовать дважды по одному и тому же вопросу:

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice = models.CharField(max_length=120)

class Question(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.CharField(max_length=200)

Есть ли способ добавить это условие на уровне модели?

1 Ответ

0 голосов
/ 05 мая 2020

К сожалению, вы не можете добавить constraint для этого, поскольку большинство баз данных не позволяют «следовать» за FOREIGN KEY s.

Что вы можете сделать, так это проверить, существует ли объект Voting уже для данного user и question, относящегося к choice:

from django.core.exceptions import ValidationError

class Voting(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    choice = models.ForeignKey(Choice, on_delete=models.CASCADE)
    answered_at = models.DateTimeField(auto_now_add=True)

    def <b>clean</b>(self, *args, **kwargs):
        if Voting.objects.exclude(
            pk=self.pk
        ).filter(
            user_id=self.user_id,
            choice__answer__choice__id=self.choice_id
        ).<b>exists()</b>:
            raise ValidationError('You can not vote twice on the same question')
        return super().clean(*args, **kwargs)

Обратите внимание, что модель не сама выполняет проверку при сохранении. Вы можете позвонить .full_clean() [Django -doc] , например, чтобы проверить ограничения. Кроме того, ModelForm выполнит проверки, если вы подтвердите форму.

...