#python #django #django-models #django-views
Вопрос:
Я создаю приложение для опроса, и я застрял на проблеме.
То, что я пытаюсь сделать :-
Я пытаюсь голосовать только за One choice at a time
, и если пользователь хочет изменить voting choice
, то пользователь также может изменить выбор. НО в это время, когда пользователь выбирает first choice
, он добавляет голосование снова и снова, и если пользователь выбирает second option
, то оба добавляют ( первый выбор и второй выбор ). НО я пытаюсь добавить только один выбор за раз.
views.py
def poll_vote(request, poll_id):
poll = get_object_or_404(Poll, pk=poll_id)
choice_id = request.POST.get('choice')
if choice_id:
choice = Choice.objects.get(id=choice_id)
vote = Vote(user=request.user, poll=poll, choice=choice)
vote.save()
print(vote)
return render(request, 'polls/poll_result.html', {'poll': poll})
else:
messages.error(
request, "No choice selected")
return redirect("polls:polls_detail_view", poll_id)
return render(request, 'polls/poll_result.html', {'poll': poll})
Я также попробовал это с poll_vote
учетом
if not poll.user_can_vote(request.user):
messages.error(request, "You already voted this poll")
return redirect("polls:polls_detail_view",poll_id=poll_id)
Это работает нормально, например :- Когда пользователь голосует first choice
, это мешает пользователю выбрать второй вариант, но я хочу, чтобы пользователь мог изменить другой вариант после голосования.
models.py
class Poll(models.Model):
owner = models.ForeignKey(User,null=True,on_delete=models.CASCADE)
text = models.TextField()
date = models.DateTimeField(default=timezone.now)
def user_can_vote(self, user):
user_votes = user.vote_set.all()
qs = user_votes.filter(poll=self)
if qs.exists():
return False
return True
class Choice(models.Model):
poll = models.ForeignKey(Poll,on_delete=models.CASCADE)
choice_text = models.CharField(max_length=30)
class Vote(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
poll = models.ForeignKey(Poll,on_delete=models.CASCADE)
choice = models.ForeignKey(Choice,on_delete=models.CASCADE)
Я понятия не имею, как заставить пользователя изменить выбор голоса после голосования.
Любая помощь была бы очень признательна.
Заранее спасибо.
Ответ №1:
Вы можете использовать update_or_create
[документы Django] для обновления существующего голосования или создания нового:
def poll_vote(request, poll_id):
poll = get_object_or_404(Poll, pk=poll_id)
choice_id = request.POST.get('choice')
if choice_id:
choice = Choice.objects.get(id=choice_id)
vote, created = Vote.objects.update_or_create(
user=request.user,
poll=poll,
defaults={'choice': choice}
)
print(vote)
return render(request, 'polls/poll_result.html', {'poll': poll})
else:
messages.error(
request, "No choice selected")
return redirect("polls:polls_detail_view", poll_id)
return render(request, 'polls/poll_result.html', {'poll': poll})
Если у вас есть какие-либо дубликаты экземпляров Vote
, вам следует сначала удалить их, прежде чем использовать это. Также вам следует добавить UniqueConstraint
[документы Django] в свою Vote
модель, чтобы предотвратить дубликаты:
class Vote(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
poll = models.ForeignKey(Poll,on_delete=models.CASCADE)
choice = models.ForeignKey(Choice,on_delete=models.CASCADE)
class Meta:
constraints = [
models.UniqueConstraint(fields=['user', 'poll'], name='unique_user_poll')
]
Ответ №2:
Нужно проверить, есть ли у этого пользователя существующий голос. Ваш код создает новое голосование каждый раз, когда публикуется форма с выбором.
choice = Choice.objects.get(id=choice_id)
if existing_vote := Vote.objects.filter(user=request.user, poll=poll).first():
existing_vote.choice = choice
existing_vote.save()
else:
vote = Vote(user=request.user, poll=poll, choice=choice)
vote.save()
return render(request, 'polls/poll_result.html', {'poll': poll})