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.

 
vanrees.org logo

Reinout van Rees

My name is Reinout van Rees and I program in Python, I live in the Netherlands, I cycle recumbent bikes and I have a model railway.

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):