检查用户是否已对某项民意调查投票

时间:2017-04-15 10:31:42

标签: python django django-models

我有一份民意调查(问题)清单,并希望检查某个User是否对某项民意调查投了赞成票。这是我的模特:

class Question(models.Model):
    has_answered = models.ManyToManyField(User)
    question_text = models.CharField(max_length=80)

    def __str__(self):
        return self.question_text

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=100)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text

当用户对投票进行投票时,这是我的观点:

def poll_answer(request):
    if request.method == 'POST':
        answer = request.POST.get('answer')
        question = request.POST.get('question')

        q = Question.objects.get(question_text=question)

        choice = Choice.objects.get(id=answer)
        choice.votes += 1
        choice.save()
        ...

我在ManyToMany模型中添加了一个Question字段,在阅读完文档之后,我认为这是链接已投票某个问题的用户列表的正确方法,但我我不确定是否诚实。最终目标是在我的模板中添加:if request.user in question.has_answered: don't display the poll

我到底该怎么做?

3 个答案:

答案 0 :(得分:0)

有很多方法可以做到这一点, 我更愿意为投票创建另一个模型:

class Vote(models.Model):
    user = models.ForeignKey(User, unique=True)

class Choice(models.Model):
    question = models.ForeignKey(Question, related_name='choices')
    choice_text = models.CharField(max_length=100)
    votes = models.ForgeinKey(Vote)

使用这些模型,您可以轻松计算投票数: 并且您可以知道用户在问题中投票的确切内容

Choice.objects.get(pk=PK).votes.count()

检测用户是否已投票:

if Vote.objects.filter(question=1, user=user_id).count() == 1
user_id voted for question 1 already

答案 1 :(得分:0)

您可以像这样创建puzzlers[2](3); 视图:

vote

上面的def vote(request, question_id): question = get_object_or_404(Question, pk=question_id) try: selected_choice = question.choice_set.get(pk=request.POST['choice']) except: return render(request, 'your_question_page.html', {'question': question, 'error_message': "Please select an option"}) else: selected_choice.votes += 1 selected_choice.save() return redirect('polls:result_page_view', question_id=question_id) 视图将提取所选选项的选项ID,但如果出现错误,例如没有选择选项,则vote块将执行并打印给定的错误消息,否则会增加投票所选选项的计数加1并保存。 希望这会对你有所帮助。

答案 2 :(得分:0)

首先,需要解决一些逻辑和原理图问题。

您正在根据可能返回多个对象的非唯一字段question_text过滤问题。您应该通过id检索问题:

q = Question.objects.get(pk=question)

或使question_text字段唯一:

question_text = models.CharField(max_length=80, unique=True)

其次,通过Python将votes递增一个可能会导致race conditions当两个用户想要同时增加投票时可能会发生F。这就是Django中存在how to define extra fields on many-to-many relationships个对象的原因,它允许您在数据库级别进行增量:

from django.db.models import F

def poll_answer(request):
    ...
    choice = Choice.objects.get(id=answer)
    choice.votes = F("votes") + 1
    choice.save()
    ...
  

我已经获得了民意调查(问题)清单,并希望检查某个用户是否对某项民意调查进行了投票。

根据您的设计,您无法,因为您没有存储投票给哪个问题的人。当用户对某个问题进行投票时,您只是递增votes字段。

一种方法是,您可以将votes字段更改为ManyToManyField并开始存储对选项进行投票的用户:

class Question(models.Model):
    text = models.CharField(max_length=80, unique=True)

    def __str__(self):
        return self.text

class Choice(models.Model):
    question = models.ForeignKey(Question)
    choice = models.CharField(max_length=100)
    votes = models.ManyToMany(User)

所以你可以检查一下用户是否按照以下方式投票:

has_voted = request.user.choice_set.filter(question=question).exists()

此外,在我看来,此处的投票操作可以充当QuestionUser模型之间的中间模型,因此您可能需要查看Django文档中的{{3}}部分。

如果我在你的鞋子里,我会做类似下面的事情:

class Question(models.Model):
    text = models.CharField(max_length=80, unique=True)
    voters = models.ManyToManyField(User, through="Vote")

class Choice(models.Model):
    question = models.ForeignKey(Question)
    text = models.CharField(max_length=100)

class Vote(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    choice = models.ForeignKey(Choice, on_delete=models.CASCADE)
    voted_at = models.DateTimeField(auto_now_add=True)