2015-12-14 142 views
0

我正在创建一个使用Django的论坛。我有很多工作,包括投票。我无法弄清楚的一件事是防止重复投票。我怎么能得到这个工作?有没有一种方法可以使用JS在HTML中只能发送一次的表单?或者我需要在视图中执行一些特殊操作?这是我的模板代码:Django投票系统:防止重复投票

{% for comment in comments %} 
<div class="ui container segment"> 
    <img class="ui avatar image" src="/{{ comment.by.userprofile.img.url }}"><b>{{ comment.by }}</b> 
    <p style="font-size: 20px">{{ comment.body }}</p> 
    <form action="" method="post"> 
     {% csrf_token %} 
     <input type="submit" value="Thumbs up" class="ui small blue button"> 
     <i class="thumbs up outline icon"></i> 
     <input type="hidden" value="{{ comment.id }}" name="comment"> 
    </form> 
    <span>{{ comment.points }}</span> 
</div> 
{% endfor %} 

和我的意见代码:

elif request.method == 'POST': 
    print request.POST 
    if 'body' in request.POST.keys(): 
     reply = ForumReply.objects.create(by=request.user, reply_to=post, body=request.POST['body']) 
     reply.save() 
     notification = Notification.objects.create(to=post.by, message='Your post "' + post.title + '" received a new reply') 
     notification.save() 
    if 'comment' in request.POST.keys(): 
     comment = post.forumreply_set.filter(pk=request.POST['comment'])[0] 
     comment.points += 1 
     comment.save() 

我的模型(每乐高Stormtroopr的要求)

class ForumReply(models.Model): 
    by = models.ForeignKey(User) 
    reply_to = models.ForeignKey(ForumPost) 
    body = models.TextField() 
    created = models.DateField(default=timezone.now()) 
    points = models.IntegerField(default=0) 
+0

向我们展示您用来存储投票的模型? –

回答

0

好的,我找到了解决我的问题的方法,但我确定它不是最优雅的。但是,它按我需要的方式工作。

所以,我所做的是在UserProfile上创建一个ManyToManyField。所有用户都与UserProfile具有OneToOne关系。

class UserProfile(models.Model): 
    user = models.OneToOneField(User) 
    bio = models.TextField(default='This user hasn\'t said anything about themselves yet') 
    img = models.ImageField(upload_to=gen_name, default="static/imgs/default/default_user.jpg") 
    points = models.IntegerField(default=0) 
    liked_replies = models.ManyToManyField(ForumReply) 

无论何时用户喜欢回复,它都会保存到该ManyToManyField。然后在视图中,它会检查该评论是否在当前用户的喜欢回复列表中,如果是,则不会添加投票。

if 'comment' in request.POST.keys(): 
    comment = post.forumreply_set.filter(pk=request.POST['comment'])[0] 
    if not comment in request.user.userprofile.liked_replies.all(): 
     print 'liked' 
     comment.points += 1 
     comment.save() 
     request.user.userprofile.liked_replies.add(comment) 
     request.user.userprofile.save() 
+0

这正是我要做的。你为什么觉得它不雅? –

+0

不确定。在网络开发方面我没有太多经验,所以如果我找到问题的解决方案,我不一定会认为这是一个好的解决方案。 –

2

你一定要防止服务器上的双重投票,而不是在JavaScript中。否则有人会写一个恶意脚本来搞乱你的投票系统数据库。有几个解决方案,让我们开始智慧最简单:

1)在服务器上,你需要检查用户之前是否投票过。添加类似以下内容:

voted_before = len(ForumReply.objects.filter(by=request.user, reply_to=post)[:1]) > 1

然后你就可以检查是否voted_beforeTrue添加新的表决之前。

2)然而,第一个解决方案是受竞赛条件。如果同时使用一个用户投了两次相同的投票,那么服务器可能无法检测到它投票过。

为了避免竞争条件,您只使用一台服务器,并且只有一个django进程正在运行,您可以使用threading.Lock来防止多次发生检查。

3)如果你使用多个服务器和分布式数据库,你需要使用一些称为事务的东西。这些通常是数据库特定的。

+0

您提供的代码不起作用。 –