Using Django’s class based views

Tags: django, plone

Django’s class based views are a welcome departure from the old-style views that were just a function. An example is best. I’ll show the same view as a function and as a class. From the views.py:

from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.generic.base import TemplateView


def _expensive_calculation(request):
    # Calculate something and cache the result.
    return 'something'


def some_view(request):
    template = 'my_app/someview.html'
    data = _expensive_calculation(request)
    return render_to_response(
        template,
        {'data': data},
        context_instance=RequestContext(request))


class SomeView(TemplateView):
    template_name = 'my_app/someview.html'

    def _expensive_calculation(self):
        # Calculate something and cache the result.
        # You can use self.request!
        return 'something'

    def get_context_data(self, **kwargs):
        return {'data': self._expensive_calculation()}

So here you have it. Regarding the function based view:

  • The some_view() function is clear and explicit.
  • But you often have helper functions strewn all over the place.
  • You have quite some repetitive code (“render_to_response(template...)”) in every view function.

Regarding the class based view:

  • You need to know some characteristics of the django base class (TemplateView), like that you need to set template_name.
  • You need to know similar things for function based views.
  • Nice: the helper function is now encapsulated within the class. Neat and clean.
  • Less boilerplate.

Oh, and you need to hook it up in your urls.py of course:

import ...

urlpatterns = patterns(
    ...
    url(r'^function_based_view/$',
        'my_app.views.some_view',
        name='function_based_view'),
    url(r'^class_based_view/$',
        my_app.views.SomeView.as_view(),
        name='class_based_view'),
    ...

No real difference there, except that you need to call .as_view() on your view class. There’s a sensible reason for that .as_view(), but it involves python and django internals that I won’t bore you with :-) Just accept it: it is a very sensible and clean solution from my point of view.

Now, this is a simple example. In real life, I think class based views will get even more useful the more you use them:

  • Common functionality in your project can be wrapped in a base class.
  • Adjusting existing views is easier: just subclass them and change a detail.
  • I think multiple output options are easier. One subclass for REST output and one for regular html? Don’t know yet, but it might help.
  • Encapsulation of helper methods inside the classes might mean a big cleanup of the regular huge amount of helper methods strewn all over the place.
blog comments powered by Disqus
 
vanrees.org logo

About me

My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.

Weblog feeds

Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):