Archive
Tags
android (3)
ant (2)
beautifulsoup (1)
debian (1)
decorators (1)
django (9)
dovecot (1)
encryption (1)
fix (4)
gotcha (2)
hobo (1)
htmlparser (1)
imaplib (2)
java (1)
json (2)
kerberos (2)
linux (7)
lxml (5)
markdown (4)
mechanize (6)
multiprocessing (1)
mysql (2)
nagios (2)
new_features (3)
open_source (5)
optparse (2)
parsing (1)
perl (2)
postgres (1)
preseed (1)
pxe (4)
pyqt4 (1)
python (41)
raid (1)
rails (1)
red_hat (1)
reportlab (4)
request_tracker (2)
rt (2)
ruby (1)
scala (1)
screen_scraping (7)
shell_scripting (8)
soap (1)
solaris (3)
sql (2)
sqlalchemy (2)
tips_and_tricks (1)
twitter (2)
ubuntu (1)
vmware (2)
windows (1)
zimbra (2)

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)))
Posted by Tyler Lesmann on July 29, 2008 at 5:56 and commented on 1 time
Tagged as: decorators django python