2009-10-06 8 views
25

Estoy haciendo una pequeña aplicación que permite a los usuarios votar los elementos hacia arriba o hacia abajo. Estoy usando Django (¡y nuevo en esto!).Django método de aumento/disminución de votos

Me pregunto, ¿cuál es la mejor manera de presentar el enlace al usuario? Como un enlace, botón u otra cosa?

Ya he hecho algo como esto en php con un marco diferente, pero no estoy seguro si puedo hacerlo de la misma manera. ¿Debería tener un método para subir/bajar el voto y luego mostrar un enlace al usuario para hacer clic? Cuando hacen clic en él, ¿realiza el método y actualiza la página?

Respuesta

11

Apenas plug and play:

RedditStyleVoting
La implementación de votación estilo reddit para cualquier modelo Django con derecho a voto
http://code.google.com/p/django-voting/wiki/RedditStyleVoting

+0

Esto podría ser útil. Solo mirándolo ahora. ¿Sabía que de devdocs.apps.kb.models import Link debería cambiarse a? –

+2

La ventaja de esto sobre el código en mi respuesta es la mejora progresiva: funcionará sin Javascript, pero puede agregar AJAX para mejorar la experiencia del usuario. –

+3

reemplace devdocs.apps.kb.models con la ruta a su archivo models.py donde define Link. Será algo así como yourprojectname.yourappname.models. –

4

¿Como un enlace, botón o algo más?

Algo más, ¿qué tal una imagen?

Cuando hacen clic en él, ¿realiza el método y actualiza la página?

Quizás podría utilizar mejor ajax para invocar un método para guardar el voto, y no actualizar nada en absoluto.

Esto es lo que viene a mi mente.

enter image description here

8

lo que haga, asegúrese de que la envíe POST y GET no; Las solicitudes GET deben nunca alterar la información de la base de datos.

+0

Tiene razón, y este principio descarta utilizar un enlace de imagen simple para volver a cargar la página. –

30

Aquí está la esencia de mi solución. Uso imágenes con jQuery/AJAX para manejar clics. Fuertemente influenciado por este sitio. Hay algunas cosas que podrían usar algo de trabajo (manejo de errores en el cliente, por ejemplo, y gran parte de ellas probablemente podrían ser refactorizadas) pero espero que el código sea útil para usted.

El HTML:

 <div class="vote-buttons"> 
     {% ifequal thisUserUpVote 0 %} 
     <img class="vote-up" src = "images/vote-up-off.png" title="Vote this thread UP. (click again to undo)" /> 
     {% else %} 
     <img class="vote-up selected" src = "images/vote-up-on.png" title="Vote this thread UP. (click again to undo)" /> 
     {% endifequal %} 
     {% ifequal thisUserDownVote 0 %} 
     <img class="vote-down" src = "images/vote-down-off.png" title="Vote this thread DOWN if it is innapropriate or incorrect. (click again to undo)" /> 
     {% else %} 
     <img class="vote-down selected" src = "images/vote-down-on.png" title="Vote this thread DOWN if it is innapropriate or incorrect. (click again to undo)" /> 
     {% endifequal %} 
     </div> <!-- .votebuttons --> 

El jQuery:

$(document).ready(function() { 

    $('div.vote-buttons img.vote-up').click(function() { 

     var id = {{ thread.id }}; 
     var vote_type = 'up'; 

     if ($(this).hasClass('selected')) { 
      var vote_action = 'recall-vote' 
      $.post('/ajax/thread/vote', {id:id, type:vote_type, action:vote_action}, function(response) { 
       if (isInt(response)) { 
        $('img.vote-up').removeAttr('src') 
         .attr('src', 'images/vote-up-off.png') 
         .removeClass('selected'); 
        $('div.vote-tally span.num').html(response); 
       } 
      }); 
     } else { 

      var vote_action = 'vote' 
      $.post('/ajax/thread/vote', {id:id, type:vote_type, action:vote_action}, function(response) { 
       if (isInt(response)) { 
        $('img.vote-up').removeAttr('src') 
         .attr('src', 'images/vote-up-on.png') 
         .addClass('selected'); 
        $('div.vote-tally span.num').html(response); 
       } 
      }); 
     } 
    }); 

La vista de Django que maneja la petición AJAX:

def vote(request): 
    thread_id = int(request.POST.get('id')) 
    vote_type = request.POST.get('type') 
    vote_action = request.POST.get('action') 

    thread = get_object_or_404(Thread, pk=thread_id) 

    thisUserUpVote = thread.userUpVotes.filter(id = request.user.id).count() 
    thisUserDownVote = thread.userDownVotes.filter(id = request.user.id).count() 

    if (vote_action == 'vote'): 
     if (thisUserUpVote == 0) and (thisUserDownVote == 0): 
     if (vote_type == 'up'): 
      thread.userUpVotes.add(request.user) 
     elif (vote_type == 'down'): 
      thread.userDownVotes.add(request.user) 
     else: 
      return HttpResponse('error-unknown vote type') 
     else: 
     return HttpResponse('error - already voted', thisUserUpVote, thisUserDownVote) 
    elif (vote_action == 'recall-vote'): 
     if (vote_type == 'up') and (thisUserUpVote == 1): 
     thread.userUpVotes.remove(request.user) 
     elif (vote_type == 'down') and (thisUserDownVote ==1): 
     thread.userDownVotes.remove(request.user) 
     else: 
     return HttpResponse('error - unknown vote type or no vote to recall') 
    else: 
     return HttpResponse('error - bad action') 


    num_votes = thread.userUpVotes.count() - thread.userDownVotes.count() 

    return HttpResponse(num_votes) 

Y las partes relevantes del modelo Tema:

class Thread(models.Model): 
    # ... 
    userUpVotes = models.ManyToManyField(User, blank=True, related_name='threadUpVotes') 
    userDownVotes = models.ManyToManyField(User, blank=True, related_name='threadDownVotes') 
+0

Gracias por eso. ¿Dónde colocas el código jquery? –

+2

Incluya el archivo jquery.js con una etiqueta de script en el encabezado, luego puede pegar esto dentro de las etiquetas de script en cualquier lugar de la página. Suelo terminar colocándolo en la misma plantilla de django que incluye el archivo como el HTML de esa parte de la página para que permanezcan juntos. jquery.com es un gran recurso si vas a empezar a hacer cosas de AJAX-y. –

+0

intenté tu código, ¡pero no pude hacer clic en los botones! –

Cuestiones relacionadas