我有一份民意调查(问题)清单,并希望检查某个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
我到底该怎么做?
答案 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()
此外,在我看来,此处的投票操作可以充当Question
和User
模型之间的中间模型,因此您可能需要查看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)