Class based views: untangling the mess - Russell Keith-Magee

Tags: django, djangocon

Russell is a Django core dev.

Class based views were introduced two years ago, but they weren’t greeted with universal acclaim. So he’s here to clear up the mess and hopefully make it all more clear for everyone.

History

  • In the beginning of Django, there were only views. Function-based views. No generic views.

  • Next, because of DRY, don’t repeat yourself, several generic views were added. Listing objects, editing an object, for instance. Editing something happens so often that a generic view inside Django seemed like a good idea.

    There are some problems here, though. The configuration you can do is limited by the arguments you can give in your URL configuration. No control over the logic view. You can’t pass in an alternative view. There’s no re-use between views.

    You could “fix” this by adding more and more arguments and allow passing in callables and so, but in the end you’re almost building what you’d already get with object oriented class inheritance… So…

  • Next: class based views. It landed in Django 1.3 after it didn’t work out to get it in 1.1 or 1.2.

What went wrong?

Then the wheels fell off. What went wrong?

  • Fundamental confusion over purpose. There were two problems being solved at the same time. The two: class based views and class based generic views.

    Class based views are only a class-based variant on function-based views that handles get/post/put/delete. Classed based views will give you a lot for free. Automatic OPTIONS requests handling. And naive HEAD handling. You wouldn’t have that with a function based view. And you can modify it.

    Class based generic views use class based views as a base. They’re re-writes of the existing function-based generic views. But a bit better and especially much more extensible.

  • Confusion over implementation choices. The reasons were good, but the reasons weren’t clear.

    The whole discussion and the choices behind it can be found in the django wiki.

    The biggest question is about instantiation. What is being instantiated? How? When? At the start, once, or for every single request? How do you pass in configuration? What’s the lifespan of an instance? Can you safely assign something onto self? What are the expectations?

    Note: the admin was already always class based. And it had state problems (assigning to self would leak state to other requests).

    In the end, all this was what resulted in the MyView.as_view(). as_view() results in a class factory. Otherwise they’d have to change the urls.py contract. A view is currently a callable. It would have to be changed to “a callable or a class”. It was a value judgment in the end.

  • Ravioli code. It wasn’t spagghetti code, but ravioli. A package with unknown contents.

    The generic class based views are made with a whole bunch of mixin classes. The edit view (UpdateView) consists of 9 (mixin) classes. See ccbv.co.uk.

    Why would you go through this 9-level madness? Yes, we have a complex class hierarchy. But the reason is that you can easily customize it.

    Ravioli tastes good! Maximum reuse of core logic. Extremely flexible. Easy to add your own functionality. But you need to learn it, that is the price you pay for the power you get. Learning means documentation, so…

  • Bad documentation. The initial documentation was bad. It is now better, but it needs to be made better still.

The biggest thing that needs fixing after the documentation is how to handle decorators like @login_required.

But… did we solve the right problems with the generic views? Modern websites have different problems. Multiple forms. Conditional forms. Continuous scrolling instead of pagination. AJAX support. PJAX (see yesterday’s ajax+django talk). Multiple “actions” per page.

Call to action

  • In discusions, always make sure you whether you mean CBV or CBGV (class based views or class based generic views).

    Suggestion made later during the questions: call the latter just “generic views”. The old function based generic views are gone, so…

  • Docs still can be improved.

  • #18830 FormCollection

  • Experiment with APIs. Django’s admin is a useful case study. Why not do that with an API and make it easier to create your custom admin?

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