django-voting: a brief tutorial

November 4th, 2008

In honor of the election day today, I’d like to give a quick tutorial on django-voting, a reusable application which gives you reddit-style voting capabilities on generic objects.

Django-Voting, itself, is quite a very well documented piece of software. Then again, that’s not saying a lot considering its from Jonathan Buchannan. All of his projects are famously documented.

Installation

The installation of this application was standard fare for a CGC app. SVN Checkout the application to a point on your pythong path and that’s about it. For me, the command was:

svn co http://django-voting.googlecode.com/svn/trunk/voting/ voting

From there, you simply add ‘voting’ to your INSTALLED_APPS, syncdb, and you’re ready to go.

Make It Work

Okay, so now that its installed, you need to pull it into a view. For this, I’m using a generic view and the template tags provided. I’m using the default monkier “object”. Below is the relevant part of the template.

{% score_for_object object as score %}
<h5>Votes <span id="score">{{ score.score }}</span> point{{ score.score|pluralize }}
         after <span id="num_votes">{{ score.num_votes }}</span> vote{{ score.num_votes|pluralize }}</h5>
<ul>
    <li><a href="#" onclick="vote('{{ object.slug }}', 'up');">I like it!</a></li>
    <li><a href="#" onclick="vote('{{ object.slug }}', 'down');">I hate it!</a></li>
    <li><a href="#" onclick="vote('{{ object.slug }}', 'clear');">I take it back! Clear my vote.</a></li>
</ul>

When clicking this textual link, it calls a “vote” function with the slug and the direction you’re casting your vote. This jQuery function is:

function vote(slug, direction) {
    $.post('/tips/'+slug+'/'+direction+'vote/', {HTTP_X_REQUESTED:'XMLHttpRequest'},
           function(data) {
               if (data.success == true) {
                   $('#score').text(data.score.score);
                   $('#num_votes').text(data.score.num_votes);
               } else {
                   alert('ERROR: ' + data.error_message);
               }
           }, 'json'
          )
}

So there are a few things here to talk about. When we click the link, the vote function is called. It takes the slug of the item we’re voting on and the direction you’re voting in and builds a url. This doesn’t present the most reusable option, but fills my use case well enough. It passes along a POST parameter which tells the voting app that this request is made via XMLHttpRequest (thereby bypassing confirmation of your vote). This url is getting passed through to a generic view provided by the django-voting application. The entry in the urls.py is below.

from django.conf.urls.defaults import *
from tips.models import Tip
from voting.views import vote_on_object

tip_dict = {
    'model': Tip,
    'template_object_name': 'tip',
    'slug_field': 'slug',
    'allow_xmlhttprequest': 'true',
}

urlpatterns = patterns('',
   url(r'^(?P[-\w]+)/(?Pup|down|clear)vote/?$', vote_on_object, tip_dict, name="tip-voting"),
)

Once the post result has been made, the javascript snippet parses the resulting JSON and updates the result via jQuery’s text() function. And there we have it. A simplistic example of voting on a given object. It does exactly what it needs to do in the smallest amount of code possible. A fantastic reusable app!


Comments are disabled. If that bothers you, please contact me on twitter at @justinlilly and let me know.