Submit Blog  RSS Feeds

Wednesday, March 21, 2012

A django login_required decorator that preserves URI query parameters

The default django auth module provides some awesome function decorators - login_required and permission_required. These decorators provide a flexible authorisation mechanism, each time a user tries to access a resource he is not permitted to view (modify or do anything with it) he is redirected to the login page. The user has a chance authenticate himself or provide new credentials (in case he was already authenticated but was lacking permissions), and if the authentication process is completed successfully the resource may be accessed.

In most cases using these decorators solves the problem of protecting resources while keeping the code (and the user interface) clean.

A problem occurs when we try to access a protected resource while attaching some URI query parameter, ex. http://example.com/resource/?foo=1&bar=example. We get redirected to the login page, and after providing our credentials we get redirected back to http://example.com/resource/ ... and the query parameters are gone!

Sadly the default login_required decorator does not preserve them... we have to provide our own decorator:

1. def resource_login_required(some_view):
2.     def wrapper(request, *args, **kw):
3.         if not request.user.is_authenticated():
4.             params = map(lambda x: "%s=%s&" % \
                  (x[0],x[1]), request.GET.items())
5.             return HttpResponseRedirect( \
                  "/login/?%snext=%s" % \              
                 ("".join(params),request.path))
6.         else:
7.             return some_view(request, *args, **kw)
8.     return wrapper

Line 4 is the key instruction, the presented lambda expression maps the parameter key-value pairs to an URI scheme query parameter representation. Next we concatenate the parameters with the original request path - this is it, after performing a successful login we should be redirected to the requested resource along with the request query parameters.

This decorator may by used just like the prevoiusly mentioned ones:

1.  @resource_login_required
2.  def my_view(request):
3.      #your view code
4.      pass

Feel free to adjust this decorator to your needs. 

No comments:

Post a Comment

free counters