December 2009
November 2009
October 2009
September 2009
June 2009
April 2009
March 2009
February 2009
January 2009
December 2008
November 2008
October 2008
July 2008
June 2008
October 2007
September 2007
If you are like me, then you don't do any more coding than you have to. In Django, we have generic views which give us a lot of helpful things, like extra_content and pagination. We can copy the code and write our own views, but that isn't in good style or use of time. That's where decorators come in. We can write our decorator and then wrap the generic view with it to add functionality.
On deathcat.org, I have a few decorators. One of them provides filtering Entry objects by the user who authored them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def filtering_by_user(f): def _dec(request, queryset, *args, **kwargs): nkwargs = kwargs username = None if 'username' in nkwargs: username = nkwargs.pop('username') if not username: username = request.REQUEST.get('byuser') if username: queryset = queryset.filter(user__username=username) return f(request, queryset, *args, **nkwargs) return _dec |
The _dec funtion takes all the arguments passed to the decorated generic view. On line 3, we make a copy of the keyword arguments of the function. You have to do this or the decorator will not be able to modify the keyword arguments of the function we are decorating.
On lines 6 and 7, we first check to see if a keyword argument username has been passed to the decorated view. If there is, we are going to store it and pop it out of the nkwargs dictionary. If we don't remove username from the keyword arguments, the generic view will fail. Generic views don't take username as an argument.
On the next two lines, we check if we have a username stored yet. If we don't, then we are going to attempt to pull it from the GET and POST values.
Lines 10 and 11 will filter the queryset, if we have obtained a username.
On line 13, we call the view we are decorating with the modified keyword arguments and queryset. After that, we are simply returning execution to the caller of the decorator.
That's great! Now, how do we use this decorator? In your views.py, you simply import the decorator and place the generic view in the arguments like so:
from django.views.generic.list_detail import object_list from decorators import filtering_by_user entry_list = filtering_by_user(object_list)
You can even apply multiple decorators.
entry_list = sorting(filtering_by_user(filtering_by_cat(object_list)))
