首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django投票制度:防止重复投票

Django投票制度:防止重复投票
EN

Stack Overflow用户
提问于 2015-12-14 03:57:18
回答 2查看 459关注 0票数 0

我正在创建一个使用Django的论坛。我有很多工作要做,包括投票。我唯一搞不懂的就是防止重复投票。我怎么才能让这个起作用?有没有一种方法可以用JS制作一个HTML表单,只能发送一次?还是我要在视野里做一些特殊的手术?下面是模板中的代码:

代码语言:javascript
复制
{% 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 %}

我在视图中的代码:

代码语言:javascript
复制
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()

和我的模型(根据乐高风暴部队的要求)

代码语言:javascript
复制
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)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-14 13:10:59

好吧,我找到了解决问题的办法,但我肯定这不是最优雅的。然而,它的工作,因为我需要它。

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

代码语言:javascript
复制
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中。然后,在视图中,它检查该评论是否在当前用户喜欢的回复列表中,如果是的话,它不会添加投票。

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2015-12-14 04:10:17

您肯定希望防止在服务器上进行双重投票,而不是在javascript中。否则,有人可能会编写恶意脚本来破坏您的投票系统数据库。有几个解决方案,让我们从最简单的开始:

1)在服务器上,您需要检查用户以前是否投票。添加如下内容:

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

然后,在添加新的选票之前,可以检查voted_before是否为True

2)然而,第一个解决方案受种族条件的影响。如果一个用户simultaneously进行两次相同的投票,服务器可能不会检测到它以前投过票。

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

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34259520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档