Let’s Be Lazy-Productive: Class-Based Generic Views

We, programmers, are lazy. We despise repetitive tasks and are bored by monotonous project requirements. As much as possible, we automate processes and use abstractions for patterns that we always use in our work. And yet, despite being lazy, we also want to be efficient and productive. Can we really be lazy and efficient and productive, all at the same time?

Since Django 1.3, generic views for Django were implemented using classes instead of functions. With these new class-based generic views, writing view code is easier, faster and more organized. In addition to that, we benefit from having a cleaner, more reusable, and more structured code base. We used to write function-based views like this one:

For views that really do something, we might have ended up writing the following:

And that is just for a single model. It’s not uncommon for us to have a slew of models in our projects, each requiring their own detail, list and edit views. With the old function-based views, our view code is doomed to bloat. Django 1.2 tried DRYing views with their generic views, but, in my opinion, this just transferred the bloat from our views to our urlconfs. Django 1.2 generic views also still seemed to be a bad pattern as reusability is very limited.

With class-based generic views, we could write our previous snippet as:

Now, that’s compact code—we can clearly see that we have an update view that uses MyObjectModelForm for updating MyObject instances and whose results are rendered using the single_object.html template. Class-based generic views also save us from writing boilerplate code that we would have written with function-based views.

Not only do class-based views provide us a means of writing compact code, they also provide us a means of writing highly reusable view code. Again, suppose we have several models that need an update view. We could just rewrite our implementation above as:

That’s all we have to write to create the required update views for the rest of the models that we have. In case we want some custom behavior for MyObject3’s update view, we could still inherit from the BaseUpdateView that we have and modify the parts that we need to. Writing mixins is also a good way of extending the capabilities of our existing views:

The main drawback of Django’s class-based generic views is its learning curve. Developers new to Django who wants to dive immediately into class-based generic views might have a hard time doing so, but once familiar with the inner workings of this feature of the framework, they’ll start writing clean, compact, reusable and customizable view code in no time. I recommend this unofficial documentation site and (of course) Django’s source code as the main references for class-based generic views.

Given the power of Django’s class-based generic views, do we still have room for more laziness? Of course we do, with the help of django-braces! We still often write a lot of boilerplate code even if we already use class-based generic views. Consider our BaseUpdateView above. We would have to override the dispatch methods for similar views that require logged-in users. Luckily, django-braces already implemented a neat mixin for us:

Or what if updating of MyObject2 instances is now done via AJAX? Guess what, django-braces also have mixins for this use-case:

Django-braces has plenty of other mixins that we can plug into our existing views to easily add more functionality to them. The most useful ones that I’ve found are CsrfExemptMixin and FormMessagesMixin for form processing, SuperuserRequiredMixin and the similar StaffuserRequiredMixin for access control, and MessageMixin for displaying messages created using Django’s messages framework. And if those still doesn’t fill the bill, we are free to fork the project to add our own mixins.

Being lazy doesn’t have to mean being unproductive. With the right tools, we could eliminate the boring, repetitive, and inefficient aspects of our work, allowing us to have laser focus on what really matters. What I have mentioned here is just a very small subset of all the available tools that we, Django developers, can use to be more lazy and yet more efficient and productive at the same time.