Tuesday, August 31, 2010

Django's permalink decorator

Django's documentation includes a brief section about the permalink decorator:

from django.db import models

def get_absolute_url(self):
    return ('people_view', [str(self.id)])
So what does permalink actually do? Actually, the best way is to look inside the __init__.py file stored inside the django.db.models directory:
def permalink(func):
    Decorator that calls urlresolvers.reverse() to return a URL using                                                                                                 
    parameters returned by the decorated function "func".                                                                                                               
    "func" should be a function that returns a tuple in one of the                                                                                                      
    following formats:                                                                                                                                                  
        (viewname, viewargs)                                                                                                                                            
        (viewname, viewargs, viewkwargs)                                                                                                                                
    from django.core.urlresolvers import reverse
    def inner(*args, **kwargs):
        bits = func(*args, **kwargs)
        return reverse(bits[0], None, *bits[1:3])
    return inner
So essentially permalink() is a fancy way to invoke Django's reverse() function..it relies on a decorator pattern (If you want to understand decorators/closures really, see Matt Harrison's PyCon talk at http://python.mirocommunity.org/video/1625/pycon-2010-the-meaty-parts-of- for a really good explanation.

But basically, the function translates to:
def permalink(function get absolute_url):
  def inner(*args, **kwargs):
    bits = get_absolute_url('people_view', [str(self.id)])
    return reverse('people_view', None, str(self.id))
The *bits[1:3] expression will flatten out the list into separate list arguments. Again, watch Matt Harrison's PyCon talk since you'll get a snapshot of his 10 years of Python experience wrapped up in a 1 hour talk...

No comments:

Post a Comment