Как избежать дублирования с помощью сквозной таблицы «Многие ко многим» в Django

#django #python-3.x

#django #python-3.x

Вопрос:

Я пытаюсь создать приложение, в котором пользователи могут создавать «конкурсы» (думайте о них как о выборах), заполнять бюллетень кандидатами, а затем голосовать за них, но вместо того, чтобы отдавать один голос за одного кандидата, ранжируйте их в порядке предпочтения.

Пока это моя модель:

 class Contest(models.Model):
    contest_text = models.CharField(max_length=350)
    pub_date = models.DateTimeField('Start Date')

    def __str__(self):
        return self.contest_text


class Candidate(models.Model):
    contest = models.ForeignKey(Contest, on_delete=models.CASCADE, related_name='candidates')
    candidate_name = models.CharField(max_length=80)

    def __str__(self):
        return self.candidate_name


class Ballot(models.Model):
    contest = models.ForeignKey(Contest, on_delete=models.CASCADE, related_name='ballots')
    votes = models.ManyToManyField(Candidate, through='Preference')


class Preference(models.Model):
    candidate = models.ForeignKey(Candidate, on_delete=models.CASCADE)
    ballot = models.ForeignKey(Ballot, on_delete=models.CASCADE)
    candidate_preference = models.PositiveSmallIntegerField()
  

Однако я бы хотел, чтобы в таблице предпочтений не было двух строк для разных кандидатов, где предпочтение также одинаково. Т.Е. в одном и том же бюллетене не должно быть разрешено, чтобы:

  • Джон Доу, предпочтение = 1
  • Foo Bar, предпочтение = 1

Нужно ли мне просто контролировать это в HTML, когда кто-то отправляет голосование? Конечно, вышеуказанное должно быть разрешено, но ТОЛЬКО в том случае, если эти два голоса поступили от разных людей. Я бы предпочел также контролировать это в базе данных, если это возможно.

Ответ №1:

Я думаю, что я наткнулся на ответ…

добавление:

 class Meta:
    unique_together = ('candidate', 'ballot', 'candidate_preference')
  

делает это так, что любой из внешних ключей или настроек должен отличаться.

Теперь единственное, что нужно сделать, это убедиться, что кто-то не сможет указать одного и того же кандидата из одного и того же бюллетеня с двумя разными предпочтениями. Я полагаю, я мог бы удалить ‘candidate_preference’ из атрибута unique_together, и это выполнило бы то, что я хочу, поскольку каждый избиратель будет подавать только один бюллетень для каждого конкурса.

Комментарии:

1. Это решение. Но почему вы включили предпочтение в ограничение unique, если вы хотите разрешить только одно предпочтение для каждого кандидата и бюллетеня? Однако, разве вы не хотите связать предпочтения с пользователями?

2. В конечном итоге пользователи (т. Е. избиратели) будут связаны с бюллетенями, поэтому неявно для пользователей будет введено ограничение. На данный момент анонимные пользователи могут отправлять бюллетени, поэтому в базе данных нет класса для хранения.