Rabid Ratings for Django

22.06.2008 by azarai in ajax | django | python | snipplet | tools

For my new pet project i'd like to have some nice fancy starlike rating stuff, but without stars :-) Luckily i found one over at ajaxrain called Rabid Ratings. It uses nice looking hearts and is a out of the box combo with ajax and a php backend. Yep there was my prob again, php. So i took a look at the php backend and decided to quickly port the main logic to my django app and make it available to the public.

The code consists of a tag with its own html, a simple view and model. I think it self-explanatory.

Our model with a generic key not bound to django models:

class Rating(models.Model):
    key = models.CharField("RatingKey", max_length=256, unique=True)
    total_rating = models.IntegerField("Total Rating Sum" , default=0)
    total_votes = models.IntegerField("Total votes", default=0)
    max_stars=5

    def get_star_rating(self):
        star_rating = 0
        if self.total_votes > 0:
            star_rating = round(float( float(self.total_rating/self.total_votes) / 
                                float(100/self.max_stars)) , 1)
        return star_rating

    def get_percent(self):
        if self.total_votes > 0:
            return round(float(self.total_rating/self.total_votes) , 0)
        return 0

    class Meta:
        pass

    class Admin:
        list_display = ('key','total_rating','total_votes',)

The view called by the ajax voting part:

def do_vote(request):
    return_value = ""
    try:
        rating = Rating.objects.get(key=request.POST['id'])
        rating.total_votes += 1
        rating.total_rating += int(request.POST['vote'])
        rating.save()
        return_value = "%s/%s stars ( %s votes)" % ( rating.get_star_rating(), 
                                    rating.max_stars, rating.total_votes)
    except:
        pass
    return HttpResponse(return_value)

The tag:

def show_rating(context, rating_key):
    rating, created = Rating.objects.get_or_create(key=rating_key)
    return {
            'rating_key': rating_key,
            'total_votes': rating.total_votes,
            'total_ratings': rating.total_rating,
            'rating': rating.get_star_rating(),
            'percent': rating.get_percent(),
            'max_stars': rating.max_stars
            }
register.inclusion_tag("plaza/ratings.html", takes_context=True)(show_rating)

The tags html template:

<div id="rabidRating-{{rating_key}}-{{rating}}_{{max_stars}}" class="rabidRating ratingUnrated">
    <div class="wrapper">
        <span class="ratingFill" style="width:{{percent}}%;">
            <span class="ratingStars"></span>
        </span>
    </div>
    <div id="rabidRating-{{rating_key}}-description" class="ratingText">
        {{rating}}/{{max_stars}} stars ({{total_votes}} votes)
    </div>
</div>

Map the view in your app and change the ajax call in ratings.js, add the tag somewhere and voila happy voting :-)


comments powered by Disqus