你怎么能像Stackoverflow那样用上下键投票呢?

2024-09-28 18:58:34 发布

您现在位置:Python中文网/ 问答频道 /正文

问题

  1. 如何使Ajax按钮(向上和向下箭头)使数字可以增加或减少
  2. 如何将用户的操作保存为变量NumberOfVotesOfQuestionID

我不确定是否应该对变量使用数据库。不过,我知道还有一个更简单的方法来节省选票。

如何解决这些问题?

[编辑]

服务器端编程语言是Python。


Tags: 方法用户数据库编辑服务器端ajax数字箭头
3条回答

这是一个使用jQuery/Django的脏的/未经测试的理论实现。

我们假设上下的投票是针对像这个站点上的问题/答案的,但是这显然可以根据实际的用例进行调整。

模板

<div id="answer_595" class="answer">
  <img src="vote_up.png" class="vote up">
  <div class="score">0</div>
  <img src="vote_down.png" class="vote down">
  Blah blah blah this is my answer.
</div>

<div id="answer_596" class="answer">
  <img src="vote_up.png" class="vote up">
  <div class="score">0</div>
  <img src="vote_down.png" class="vote down">
  Blah blah blah this is my other answer.
</div>

Javascript

$(function() {
    $('div.answer img.vote').click(function() {
        var id = $(this).parents('div.answer').attr('id').split('_')[1];
        var vote_type = $(this).hasClass('up') ? 'up' : 'down';
        if($(this).hasClass('selected')) {
            $.post('/vote/', {id: id, type: vote_type}, function(json) {
                if(json.success == 'success') {
                    $('#answer_' + id)
                     .find('img.' + vote_type);
                     .attr('src', 'vote_' + vote_type + '_selected.png')
                     .addClass('selected');
                    $('div.score', '#answer_' + id).html(json.score);
                }
            });
        } else {
            $.post('/remove_vote/', {id: id, type: vote_type}, function(json) {
                if(json.success == 'success') {
                    $('#answer_' + id)
                     .find('img.' + vote_type);
                     .attr('src', 'vote_' + vote_type + '.png')
                     .removeClass('selected');
                    $('div.score', '#answer_' + id).html(json.score);
                }
            });                
        }
    });
});

Django视图

def vote(request):
    if request.method == 'POST':
        try:
            answer = Answer.objects.get(pk=request.POST['id'])
        except Answer.DoesNotExist:
            return HttpResponse("{'success': 'false'}")

        try:
            vote = Vote.objects.get(answer=answer, user=request.user)
        except Vote.DoesNotExist:
            pass
        else:
            return HttpResponse("{'success': 'false'}")

        if request.POST['type'] == 'up':
            answer.score = answer.score + 1
        else:
            answer.score = answer.score - 1

        answer.save()

        Vote.objects.create(answer=answer,
                            user=request.user,
                            type=request.POST['type'])

        return HttpResponse("{'success':'true', 'score':" + answer.score + "}")
    else:
        raise Http404('What are you doing here?')

def remove_vote(request):
    if request.method == 'POST':
        try:
            answer = Answer.objects.get(pk=request.POST['id'])
        except Answer.DoesNotExist:
            return HttpResponse("{'success': 'false'}")

        try:
            vote = Vote.objects.get(answer=answer, user=request.user)
        except Vote.DoesNotExist:
            return HttpResponse("{'success': 'false'}")
        else:
            vote.delete()

        if request.POST['type'] == 'up':
            answer.score = answer.score - 1
        else:
            answer.score = answer.score + 1

        answer.save()

        return HttpResponse("{'success':'true', 'score':" + answer.score + "}")
    else:
        raise Http404('What are you doing here?')

是的。当我开始回答这个问题时,我并不打算写这么多,但我有点忘乎所以了。你仍然错过了一个在页面首次加载时获得所有选票的初始请求,但我将把它留给读者作为练习。不管怎样,如果您实际上是在使用Django,并且对Stackoverflow投票的更测试/实际的实现感兴趣,我建议您查看cnprog.com的{a1},这是用Python/Django编写的Stackoverflow的中文克隆。他们发布了他们的代码,这是相当体面的。

有几点没人提过:

  • 更改数据库状态时不希望使用GET。否则我可以在我的站点上放置一个带有src="http://stackoverflow.com/question_555/vote/up/answer_3/"的图像。
  • 你还需要csrf (Cross Site Request Forgery) protection
  • 您必须记录每个投票的人,以避免人们为某个特定问题多次投票。这是通过IP地址还是用户ID。

您可以创建按钮,可以是链接或图像或其他。现在将一个JavaScript函数连接到每个按钮的click事件。单击时,函数将触发并

  • 向服务器代码发送一个或多或少写着+1或-1的请求。
  • 服务器代码接管。这将取决于您使用(或不使用)的框架和其他一些东西。
  • 代码连接到数据库并运行一个查询来+1或-1分数。这种情况的发生方式会因数据库设计的不同而有很大的差异,但它会类似于UPDATE posts SET score=score+1 WHERE score_id={{insert id here}};
  • 根据数据库的说明,服务器返回一个成功代码或一个失败代码作为AJAX请求响应。
  • 响应被异步发送到AJAX。
  • 如果是成功代码,JS response函数将更新分数,如果是失败代码,则显示错误。

您可以将代码存储在变量中,但这很复杂,取决于您对代码运行时环境的语义了解程度。无论如何,它最终都需要被推送到持久存储,因此100%使用数据库是一个很好的初始解决方案。当优化性能的时候到了,世界上有足够的软件来缓存数据库查询,让你感到昏昏欲睡,所以这没什么大不了的。

相关问题 更多 >