32 votes

Comment faire un bouton de vote de haut en bas comme dans Stackoverflow ?

Problèmes

  1. comment faire un bouton Ajax (flèches vers le haut et vers le bas) pour que le nombre puisse augmenter ou diminuer ?
  2. Comment sauvegarder l'action d'un utilisateur dans une variable NumberOfVotesOfQuestionID ?

Je ne sais pas si je dois utiliser la base de données ou non pour la variable. Cependant, je sais qu'il existe aussi un moyen plus simple de sauvegarder le nombre de votes.

Comment pouvez-vous résoudre ces problèmes ?

[modifier]

Le langage de programmation côté serveur est Python.

59voto

Paolo Bergantino Points 199336

Il s'agit d'une mise en œuvre théorique sale/non testée utilisant jQuery/Django.

Nous allons supposer que le vote vers le haut et vers le bas est pour les questions/réponses comme sur ce site, mais cela peut évidemment être adapté à votre cas d'utilisation réel.

Le modèle

<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);
                }
            });                
        }
    });
});

Vues de 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?')

Oups. Lorsque j'ai commencé à répondre à cette question, je n'avais pas l'intention d'écrire autant, mais je me suis un peu emporté. Il manque toujours une requête initiale pour obtenir tous les votes lorsque la page est chargée pour la première fois, mais je laisserai cet exercice au lecteur. Quoi qu'il en soit, si vous sont Si vous utilisez Django et que vous êtes intéressé par une implémentation plus testée/réelle du vote de Stackoverflow, je vous suggère de consulter la page code source pour cnprog.com, un clone chinois de Stackoverflow écrit en Python/Django. Ils ont publié leur code et il est assez décent.

8voto

Tom Viner Points 2323

Quelques points que personne n'a mentionnés :

  • Vous ne voulez pas utiliser GET lorsque vous changez l'état de votre base de données. Sinon je pourrais mettre une image sur mon site avec src="http://stackoverflow.com/question_555/vote/up/answer_3/" .
  • Vous devez également Protection contre la contrefaçon de requêtes intersites (csrf)
  • Vous devez enregistrer qui fait chaque vote pour éviter que les gens votent plus d'une fois pour une question particulière. Que ce soit par adresse IP ou par identifiant d'utilisateur.

3voto

Hao Lian Points 1518

Vous créez les boutons, qui peuvent être des liens, des images ou autre. Reliez maintenant une fonction JavaScript à l'événement de clic de chaque bouton. Au moment du clic, la fonction se déclenche et

  • Envoie une requête au code du serveur qui dit, plus ou moins, +1 ou -1.
  • Le code du serveur prend le relais. Cela varie énormément en fonction du framework que vous utilisez (ou non) et d'un tas d'autres choses.
  • Le code se connecte à la base de données et exécute une requête pour +1 ou -1 le score. La façon dont cela se passe varie énormément en fonction de la conception de votre base de données, mais ce sera quelque chose comme UPDATE posts SET score=score+1 WHERE score_id={{insert id here}}; .
  • En fonction de ce que dit la base de données, le serveur renvoie un code de réussite ou un code d'échec comme réponse à la demande AJAX.
  • La réponse est envoyée à AJAX, de manière asynchrone.
  • La fonction de réponse JS met à jour le score si c'est un code de réussite, affiche une erreur si c'est un échec.

Vous peut stocker le code dans une variable, mais cela est compliqué et dépend de la façon dont vous connaissez la sémantique de l'environnement d'exécution de votre code. Il doit de toute façon être poussé vers un stockage persistant, donc utiliser la base de données à 100% est une bonne solution initiale. Lorsque le temps de l'optimisation des performances arrive, il y a suffisamment de logiciels dans le monde pour mettre en cache les requêtes de la base de données pour vous faire perdre la tête, donc ce n'est pas un gros problème.

0voto

Zoran Zaric Points 565

Je pense que les réponses à ces questions sont trop longues pour stackoverflow.

Je recommande de stocker les votes dans une base de données.

Vous ne mentionnez pas de langage de programmation côté serveur.

veuillez nous donner plus d'informations

Ce site pourrait vous aider à démarrer

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X