Disclaimer: the views and opinions presented here are mine and do not reflect those of my employer, Mirumee Software.

Class-based views were first introduced in 2010 and back then my younger self did his best to push back on the current approach. Unfortunately I was so upset with the initial implementation that in the end I came across as a condescending asshole, apologies for that. Six years later I still try to avoid them and I figured I might as well share some of the reasons with you.

Before I continue I want you to know that I do recognize that class-based views are a tool and as such may be a valuable resource. There surely are cases where class-based views provide an adequate solution to a problem. The part I find troubling is that it seems to me that they are being widely accepted as the only way forward.

Working with class-based views is a journey in a maze full of dead-ends

Working with generic views and class-based views in particular is pretty straight-forward when your goal is a well-defined stationary target. That’s why these views work so well in tutorials.

Unfortunately programming is nothing like that. Your customers (even the internal ones) have their business requirements and the goal posts move with every iteration. When those requirements change class-based views often force you to take a dozen steps back before you’re able to move forward.

Let me stress this: moving from one base class to another is often a prohibitively expensive refactoring task.

At least in the end you write less code, you saw that in the examples. Well, the “generic” part turns out to be a marketing lie. The promise of having a generic solution to every problem is tempting but each generic view is a tiny rabbit hole.

Adding a form to a detail view? Just a couple of lines. Adding a second form to a form view? Easy enough. A third form? Done. The code is a mess but you keep digging deeper. There’s rarely an obvious place to add your changes so most of your business logic lands in get_context_data that eventually starts to resemble a traditional function-based view. Except its surrounded by all kinds of one-line method overrides for things like get_success_url that have long since lost their original meaning.

Of course you can keep refactoring logic into new base classes but under what circumstances does a generic “three forms where the third one is only validated if the second contains a Thursday” view start to sound like a good idea? Once you rename form_valid to wishlist_form_valid all of the time-saving form mix-ins become useless.

And if requirements change do you repurpose your old view or do you come up with a new semantic abstraction and a bunch of new mix-ins?

Here’s a proof that class-based views are hard to get right: Django itself has recently accepted a pull request that resulted in a security hole caused by conveniently stuffing view logic into get_context_data .

Debugging is very hard

Most of the class-based view logic is implemented by generic methods. Methods themselves often live in mix-ins. And you’re encouraged to only override some attributes and helpers and let the generic code implement control flow and abstract the complexity away.

Here’s the catch: a typical stack trace will contain very little if any of your project’s actual code.