As seen in Getting started, a model instance can be voted and can have an associated score only if its model class is handled. Being handled, for a model, means it is registered with an handler.
We have seen how to do that:
from ratings.handlers import ratings ratings.register(Film)
The handler class is an optional argument of the
and, if not provided, the default
ratings.handlers.RatingHandler handler is
The previous code can be written:
from ratings.handlers import ratings, RatingHandler ratings.register(Film, RatingHandler)
ratings.register can also accept a list
of model classes in place of a single model; this allows easier
registration of multiple models with the same handler class, e.g.:
from ratings.handlers import ratings, RatingHandler ratings.register([Film, Series], RatingHandler)
Where should this code live? You can register handlers anywhere you like. However, you’ll need to make sure that the module it’s in gets imported early on so that the model gets registered before any voting is performed or rating is requested. This makes your app’s models.py a good place to put the above code.
The default rating handler provides only one 1-5 ranged (without decimal places) score for each content object, and allows voting only for authenticated users. It also allows user to delete and change their vote.
We can, however, override some options while registering the model. For instance, if we want 1-10 ranged votes with a step of 0.5 (half votes), and we don’t want users to delete their votes, we can give these options as kwargs:
from ratings.handlers import ratings, RatingHandler ratings.register(Film, RatingHandler, score_range=(1, 10), score_step=0.5, can_delete_vote=False)
The handler manages the voting form too, and, by default the widget used to render the score is a simple text input. If you want to use the more cool star rating widget, you can do:
from ratings.handlers import ratings from ratings.forms import StarVoteForm ratings.register(Film, form_class=StarVoteForm)
For a list of all available built-in options, see Handlers reference.
However, there are situations where the built-in options are not sufficient.
What if, for instance, you want only active objects to be voted for a
As in Django own
contrib.admin.ModelAdmin, you can write subclasses of
RatingHandler to override the methods which actually perform the voting
process, and apply any logic they desire.
Here is an example meeting the staff users needs:
from ratings.handlers import ratings, RatingHandler class MyHandler(RatingHandler): def allow_vote(self, request, instance, key): allowed = super(MyHandler, self).allow_vote(request, instance, key) return allowed and instance.is_active ratings.register(Film, MyHandler)
In the above example, the
allow_vote method is called before any voting
attempt, and takes the current request, the instance being voted and
The key is a string representing the type of rating we are giving to an
object. For example, the same film can be associated with multiple types of
rating (e.g. a score for the photography, one for the direction, one for
the music, and so on): a user can vote the music or the direction, so the
key can be used to distinguish music from direction. In fact, the key can
even be the string
'music' or the string
The default key is
Don’t worry: we will talk more about rating keys in Usage and examples.
Handlers are not only used to manage and customize the voting process, but also grant a simplified access to the underneath Django models api.
First, we have to obtain the handler instance associated with our model:
from ratings.handlers import ratings handler = ratings.get_handler(Film)
ratings.get_handler returns None if model is not registered, and
can take a model instance too:
from ratings.handlers import ratings film = Film.objects.latest() handler = ratings.get_handler(film)
What we can do with the handler?
For instance, we can get the
'main' score or our film:
score = handler.get_score(film, 'main') if score: print 'Average score:', score.average print 'Number of votes:', score.num_votes print 'Total score:', score.total else: print u'Nobody voted %s' % film
Or we can check if current user has voted our film:
voted = handler.has_voted(film, 'main', request.user)
See Handlers reference for a detailed explanation of other utility methods
of handlers, and of
ratings.handlers.ratings registry too.
And in Models reference you will find the lower level Django model’s API.
It could be clear now that the rating handler is a layer of abstraction above Django models and forms, and handlers are used by templatetags and views too. This way, building our own handlers means we can customize the behaviour of the entire application.