Как вы можете сделать кнопку голосования вверх-вниз, как в Stackoverflow? - PullRequest
31 голосов
/ 05 апреля 2009

Проблемы

  1. как сделать кнопки Ajax (стрелки вверх и вниз) так, чтобы число могло увеличиваться или уменьшаться
  2. как сохранить действие пользователя в переменной NumberOfVotesOfQuestionID

Я не уверен, должен ли я использовать базу данных или нет для переменной. Однако я знаю, что есть и более простой способ сэкономить количество голосов.

Как вы можете решить эти проблемы?

[править]

Серверный язык программирования - Python.

Ответы [ 4 ]

59 голосов
/ 05 апреля 2009

Это грязная / непроверенная теоретическая реализация с использованием 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);
                }
            });                
        }
    });
});

Джанго просмотров

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, Китайский клон Stackoverflow написан на языке Python / Django. Они выпустили свой код, и он довольно приличный.

8 голосов
/ 06 апреля 2009

Пара моментов, о которых никто не упомянул:

  • Вы не хотите использовать GET при изменении состояния вашей базы данных. В противном случае я мог бы разместить изображение на моем сайте с src="http://stackoverflow.com/question_555/vote/up/answer_3/".
  • Вам также необходима защита csrf (Подделка межсайтовых запросов)
  • Вы должны указать , кто делает каждый голос , чтобы люди не голосовали более одного раза за определенный вопрос. Является ли это IP-адресом или идентификатором пользователя.
3 голосов
/ 05 апреля 2009

Вы создаете кнопки, которые могут быть ссылками или изображениями или чем-то еще. Теперь подключите функцию JavaScript к событию нажатия каждой кнопки. При нажатии срабатывает функция и

  • Отправляет запрос к коду сервера, который говорит, более или менее, +1 или -1.
  • Код сервера вступает во владение. Это будет сильно отличаться в зависимости от того, какую платформу вы используете (или не используете) и кучу других вещей.
  • Код подключается к базе данных и запускает запрос +1 или -1 к баллу. Как это произойдет, будет сильно отличаться в зависимости от вашей базы данных, но это будет что-то вроде UPDATE posts SET score=score+1 WHERE score_id={{insert id here}};.
  • В зависимости от того, что говорит база данных, сервер возвращает код успеха или код ошибки в качестве ответа на запрос AJAX.
  • Ответ отправляется в AJAX асинхронно.
  • Функция ответа JS обновляет счет, если это код успеха, отображает ошибку, если это сбой.

Вы можете хранить код в переменной, но это сложно и зависит от того, насколько хорошо вы знаете семантику среды выполнения вашего кода. В конце концов, в любом случае его необходимо перенести в постоянное хранилище, поэтому использование базы данных на 100% является хорошим начальным решением. Когда приходит время для оптимизации производительности, в мире появляется достаточно программного обеспечения для кэширования запросов к базе данных, чтобы вы чувствовали себя обманутыми, поэтому это не так уж и сложно.

0 голосов
/ 05 апреля 2009

Я думаю, ответы на эти вопросы слишком длинные для stackoverflow.

Я бы рекомендовал хранить голоса в базе данных.

Вы не упоминаете язык программирования на стороне сервера.

пожалуйста, дайте нам больше информации

Это может помочь вам начать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...