03.12.09

callables in django URLconfs and dispatch by HTTP verb

Posted in Web authoring, python at 11:57 am by karl

This information is lifted from RESTful Web Services, which is well worth the read if you build web applications. See chapter 12, page 354 onwards to find out about using django RESTfully.

Django users will know that it’s possible to use callable objects instead of strings in URLconfs. One great use of this feature is to dispatch HTTP requests to different functions based on the HTTP verb. This turned out to be useful for me recently when I had to implement HTTP DELETE for some resources. Instead of having one big method like this

if 'GET' == request.method:
    ... do something ...
elif 'POST' == request.method:
    ... do something else ...
elif 'DELETE' == request.method:
    ... do somethign else ...

we can use python’s reflection capabilities and dispatch to different methods based on which HTTP verb was used. First we define a base class like this:

class HTTPVerbDispatcher:
    def __call__(self, request, *args, **kwargs):
        try:
            fn = getattr(self, "do_%s" % request.method)
        except AttributeError: # this method is not supported
            allowed_methods = [m.lstrip("do_") for m in dir(self) if m.startswith("do_")]
            return HttpResponseNotAllowed(allowed_methods)
        return fn(request, *args, **kwargs)

Any classes deriving from this will call a method called do_GET, do_POST etc. based on the value of request.method. We can create a class in views.py like this:

class BlogEntryView(HTTPVerbDispatcher):
    def do_GET(self, request, id):
        .... handle GET request - view object ...

    def do_POST(self, request, id):
        .... handle POST request - view object ...

    def do_DELETE(self, request, id):
        .... handle DELETE request - view object ...

Finally, we set up our URLconf to use the BlogEntryView callable:

from django.conf.urls.defaults import *

from myapp.views import BlogEntryView

urlpatterns = patterns('',
    (r'^(?P<id>d+)$', BlogEntryView()),
)

Leave a Comment

You must be logged in to post a comment.