30 votos

¿Cómo se puede hacer un botón para votar hacia arriba y hacia abajo como en Stackoverflow?

Problemas

  1. cómo hacer un botón Ajax (flechas hacia arriba y hacia abajo) de manera que el número pueda aumentar o disminuir
  2. cómo guardar la acción de un usuario en una variable NumberOfVotesOfQuestionID

No estoy seguro de si debo utilizar la base de datos o no para la variable. Sin embargo, sé que hay una manera más fácil también para guardar el número de votos.

¿Cómo puede resolver esos problemas?

[editar]

El lenguaje de programación del lado del servidor es Python.

58voto

Paolo Bergantino Puntos 199336

Esta es una implementación teórica sucia/no probada usando jQuery/Django.

Vamos a suponer que la votación hacia arriba y hacia abajo es para las preguntas/respuestas como en este sitio, pero eso obviamente se puede ajustar a su caso de uso en la vida real.

La plantilla

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

Vistas 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?')

Vaya. Cuando empecé a responder a esta pregunta no pretendía escribir tanto pero me dejé llevar un poco. Sigue faltando una petición inicial para obtener todos los votos cuando se carga la página por primera vez y tal, pero eso lo dejaré como ejercicio para el lector. De todos modos, si son de hecho usando Django y está interesado en una implementación más probada/real de la votación de Stackoverflow, le sugiero que revise el código fuente para cnprog.com, un clon chino de Stackoverflow escrito en Python/Django. Liberaron su código y es bastante decente.

7voto

Tom Viner Puntos 2323

Un par de puntos que nadie ha mencionado:

  • No es conveniente utilizar GET cuando se cambia el estado de la base de datos. De lo contrario, podría poner una imagen en mi sitio con src="http://stackoverflow.com/question_555/vote/up/answer_3/" .
  • También necesita protección csrf (Cross Site Request Forgery)
  • Debe registrar que hace cada voto para evitar que la gente vote más de una vez por una determinada pregunta. Ya sea por dirección IP o por ID de usuario.

3voto

Hao Lian Puntos 1518

Tú creas los botones, que pueden ser enlaces o imágenes o lo que sea. Ahora engancha una función JavaScript al evento de clic de cada botón. Al hacer clic, la función se dispara y

  • Envía una petición al código del servidor que dice, más o menos, +1 o -1.
  • El código del servidor toma el relevo. Esto variará mucho dependiendo del framework que utilices (o no) y un montón de cosas más.
  • El código se conecta a la base de datos y ejecuta una consulta para +1 o -1 la puntuación. La forma en que esto ocurra variará mucho dependiendo del diseño de su base de datos, pero será algo como UPDATE posts SET score=score+1 WHERE score_id={{insert id here}}; .
  • Dependiendo de lo que diga la base de datos, el servidor devuelve un código de éxito o un código de fracaso como respuesta a la solicitud AJAX.
  • La respuesta se envía a AJAX, de forma asíncrona.
  • La función de respuesta JS actualiza la puntuación si es un código de éxito, muestra un error si es un fracaso.

Usted puede almacenar el código en una variable, pero esto es complicado y depende de lo bien que conozcas la semántica del entorno de ejecución de tu código. De todos modos, en algún momento hay que pasar el código a un almacenamiento persistente, por lo que utilizar la base de datos al 100% es una buena solución inicial. Cuando llegue el momento de optimizar el rendimiento, hay suficiente software en el mundo para almacenar en caché las consultas a la base de datos como para que te sientas mareado, así que no es un gran problema.

0voto

Cowboyenvy Puntos 16

Creo que las respuestas a estas preguntas son demasiado largas para stackoverflow.

Yo recomendaría almacenar los votos en una Base de Datos.

No menciona un lenguaje de programación del lado del servidor.

por favor, denos más información

Este puede ayudarte a empezar

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X