Django's CVB - Roadmap?

399 views
Skip to first unread message

Victor Hooi

unread,
Jun 1, 2012, 10:14:50 AM6/1/12
to django-d...@googlegroups.com
Hi,

I was reading the blog post from Luke Plant recently on his views on Django's CBVs:


As well as the reply here:


The reason for my post - is there anything from the Django core as a whole on this? What's the future roadmap like in terms of CBV's? Are there going to be any changes to it, or are we safe to assume things will be as they are now.

I noticed that the documentation for CBV's is still a bit...bare? Is there any movement on the documentation or examples front?

Cheers,
Victor

Jacob Kaplan-Moss

unread,
Jun 1, 2012, 10:54:23 AM6/1/12
to django-d...@googlegroups.com
On Fri, Jun 1, 2012 at 10:14 AM, Victor Hooi <victo...@gmail.com> wrote:
> The reason for my post - is there anything from the Django core as a whole
> on this? What's the future roadmap like in terms of CBV's? Are there going
> to be any changes to it, or are we safe to assume things will be as they are
> now.

I think as a whole we're.... divided. Luke's opinions differ from
mine, and it's entirely unclear to me who's "right" or even if there's
a "right" to be had. And that's just the two of us!

I think this might be a situation where we need some more feedback
from the community and some more time to decide what the right move
here is.

So... what do *you* think?

Jacob

Donald Stufft

unread,
Jun 1, 2012, 12:35:47 PM6/1/12
to django-d...@googlegroups.com
I tend to agree, in general, with the reply that there should be a function based api
to cover the 80% use case, but in the case of Django's CBV's this is likely
covered by the as_view method.
--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To post to this group, send email to django-d...@googlegroups.com.
To unsubscribe from this group, send email to django-develop...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.

Michael

unread,
Jun 1, 2012, 1:04:52 PM6/1/12
to django-d...@googlegroups.com
I am not ready to judge right now wether they are a good idea or not. 

I can completely agree that documentation makes the views more difficult then they actually are. Every time I create a new view, I find myself going to the source. I think this is a case where the learning curve initially is a little steeper so better examples and best-practices will really help with people's implementation and also this discussion.

I have been wanting to write up documentation every time I go to the source, but sadly haven't had the time. Maybe I will soon.

Adam "Cezar" Jenkins

unread,
Jun 1, 2012, 1:21:43 PM6/1/12
to django-d...@googlegroups.com
On Fri, Jun 1, 2012 at 12:04 PM, Michael <newma...@gmail.com> wrote:
I am not ready to judge right now wether they are a good idea or not. 

I can completely agree that documentation makes the views more difficult then they actually are. Every time I create a new view, I find myself going to the source. I think this is a case where the learning curve initially is a little steeper so better examples and best-practices will really help with people's implementation and also this discussion.


This is the real issue. The docs. I'm trying to use CBVs exclusively in my latest project. I end up in the source most of the time. It might be good to start people out with very basic CBVs and make the docs much more of a tutorial.

Steven Cummings

unread,
Jun 1, 2012, 1:36:43 PM6/1/12
to django-d...@googlegroups.com
The docs around the provided CBVs and mixins are an issue, but also what is missing is that programmers seem to still think those that are provided should work for more cases than they probably do. When the narrative for CBVs is documented, should Django focus on mixins and state the expected limits of the provided classes? I think people are finding those limits pretty quickly (e.g., "I need more than one form on this page!"), and then perhaps conclude that CBV's are "broken". Perhaps the idea that your site or Django app may need more specific base-classes needs more promotion?

--
Steven

Iván Raskovsky

unread,
Jun 1, 2012, 3:45:28 PM6/1/12
to django-d...@googlegroups.com
Hi there, IMHO I think we are discussing two different topics here.

The first one is documentation. I've just added a page to the wiki
outlining the actual state of the CVB docs and some ideas on how we
can improve it. Please fell free to expand/object/modify/destroy what
I've written. I hope that between us all we can decide which way to
move forward regarding the documentation in an organized effort. At
least agree as a community in how to organize the docs, so we could
then have "pieces" of docs outlined to be written.

You can check it out here:
https://code.djangoproject.com/wiki/ClassBasedViewsDocs

The second one is the actual Generic CBV. From my point of view
there's a missing GCBV which I've discussed in
https://groups.google.com/d/msg/django-developers/rkh9oG603XI/By78sCl3xmsJ
. Right now I'm thinking about a different approach that I've been
discussing in #django-dev. A view that can handle any number of
"formlike objects" (eg modelforms, formsets, inline formsets),
validate and process them. This is a common problem that most projects
would be able to use.

Hope that with all this movement we can move this aspect of Django
forward. Regards,
Iván

Alex Ogier

unread,
Jun 1, 2012, 6:29:39 PM6/1/12
to django-d...@googlegroups.com
On Fri, Jun 1, 2012 at 3:45 PM, Iván Raskovsky <rask...@gmail.com> wrote:
> Hi there, IMHO I think we are discussing two different topics here.
>
> The first one is documentation...
>
> The second one is the actual Generic CBV...

There's a third complaint that several people have mentioned that is
deeper than both these problems. This is that CBVs mask control flow
and this makes them inherently harder to use. Basically, since the
order of execution of your methods is an implementation detail of the
base class, everyone needs to refer to the documentation whenever they
try to examine a CBV.

This is somewhat related to the Generic CBV problem, in that a lot of
the people who ask "Why can't I do X with a Generic CBV" are really
asking, "Why isn't there a place to put what I need into the control
flow" and the answer is "Because when flow is inverted, every
extensibility point must be explicit." Adding more extensibility
points like multiple forms does nothing to fundamentally change this,
it just changes Generic CBVs from the 80% solution to the 90% solution
to the 95% solution, etc. They will never be a 100% solution,
precisely because control flow is inverted.

This problem is a really deep one, and has parallels with other
long-term sticking points in Django, such as the app model. Apps
provide a whole bunch of piecemeal functionality: some views, some
templates, some models, some tests, some urls, and these are all
executed and/or processed by Django based on its particular
implementation. For example, instead of reading the template from the
filesystem, you call a Django library function that reaches into its
global collection of loaded templates and retrieves it for you. In
CBVs, instead of calling validate() on some form, you rely on the
internals executing something for you, which makes understanding
preconditions for various methods difficult to understand without
extensive docs.

Anyways, this is a deeper problem than "There are two things we can
fix, let's get on that."

Best,
Alex Ogier

Reinout van Rees

unread,
Jun 2, 2012, 4:42:14 PM6/2/12
to django-d...@googlegroups.com
On 01-06-12 16:54, Jacob Kaplan-Moss wrote:
>
> I think as a whole we're.... divided. Luke's opinions differ from
> mine, and it's entirely unclear to me who's "right" or even if there's
> a "right" to be had. And that's just the two of us!
>
> I think this might be a situation where we need some more feedback
> from the community and some more time to decide what the right move
> here is.
>
> So... what do *you* think?

Class based views as such are wonderful. The possibility to use them is
great, if your usecase warrants them. My company has two base CBV
classes that are used in *all* our projects. Nice for our productivity.

But...

- Hey, looky! Somebody looked at Zope's 2003 codebase and thought that
mixin classes were great! You know that Zope basically started its
zope.interface adapter machinery because those mixin classes became too
complex?

- All those generic views muck up the PR a lot. A CBV seems intended for
a generic view. But it is (more) useful outside those.


Summary: I love CBVs. The PR for them sucks because generic views turn
it into a veritable feast of mixins.


Reinout

--
Reinout van Rees http://reinout.vanrees.org/
rei...@vanrees.org http://www.nelen-schuurmans.nl/
"If you're not sure what to do, make something. -- Paul Graham"

mjl Martin J. Laubach

unread,
Jun 3, 2012, 8:41:35 AM6/3/12
to django-d...@googlegroups.com
This is the real issue. The docs.

  It's one of the issues, but I'm not really convinced it is the only one. My experience with CBV usually has gone like this:

  1.   "I need a view, let's do it with CBV"
  2.   "Oh hey, that was easy!"
  3.   "I need some more functionality...." 
  4.   Go to the source and wade through it for an hour or so to find out how
  5.   "Dang, those mixins conflict / don't work for my case / turn into a confusing patch and overridefest"
  6.   "I wish I had just used a regular view, I would have been done long ago"
  7.   (optional) Move to regular views

  I'm on the edge whether I'm too stupid or CBVs are too confusing to be worth it.

        mjl

Meshy

unread,
Jun 4, 2012, 6:00:29 AM6/4/12
to django-d...@googlegroups.com
Still sounds like an issue with the docs to me, and while they do still have some issues, I'm a big supporter of the CBVs. 

I've posted this here before, but http://ccbv.co.uk/ really helps cut out most of the pain of the "looking through the source code" stage of understanding the CBVs because it squashes the class hierarchy and allows you to "see the wood for the trees" as it were. There are UX issues and even the odd bug, but it helps. In other words: it's a work in progress, but until the docs are fixed, I think it's a very useful resource. Disclaimer: I was involved in creating it, but it's not-for-profit, and there for everyone to use.

I would really like to get involved in getting the docs to the stage where they display something more similar to this, so if you know how I could do that, I'd really like to know.

Hanne Moa

unread,
Jun 4, 2012, 10:00:50 AM6/4/12
to django-d...@googlegroups.com
On 1 June 2012 16:54, Jacob Kaplan-Moss <ja...@jacobian.org> wrote:
> I think this might be a situation where we need some more feedback
> from the community and some more time to decide what the right move
> here is.
>
> So... what do *you* think?

I've used CBV's in one app so far, and have wound up only using View
and TemplateView. For the rest it seems better to make my own methods
to deal with forms etc. and not bother with any of the mixins. Even in
that app, when I redirect I use a functional style generic view. I
prefer my urlconfs to look like config, not code.

I had planned on rewriting functional views, but... no.

I think it is important to remember the difference between CBV and
*generic* CBV. It's the latter that doesn't seem to be working very
well.


HM
Message has been deleted

Zach Mathew

unread,
Jun 4, 2012, 11:00:22 AM6/4/12
to django-d...@googlegroups.com
Glad to see this debate happening, because for a long time I felt like I was the only one who had issues with CBVs. I forced myself to use CBVs (custom and generics) on two major projects and I'm still struggling to see the real value in them.

Luke's post did an excellent job of articulating the issues, so I won't bother repeating the same arguments.

However, one of the things I find with CBVs is that it encourages a programming style that doesn't seem to go well with the TDD approach (at least in my opinion):

With FBVs, I would start writing the code for my view, satisfying the test, then going back and refactoring the view code by looking for commonalities with other views (Write code > Pass Test > Refactor)

With CBVs, I tend to start by searching for an appropriate parent/base class to subclass, then writing my custom view code and satisfying the test. I see this as forcing the refactoring first before writing custom code (Refactor > Write code > Pass Test)

Not sure if anyone else feels the same way, but it's good to hear all the different perspectives on this.

Luke Plant

unread,
Jun 4, 2012, 3:12:08 PM6/4/12
to django-d...@googlegroups.com
On 01/06/12 15:54, Jacob Kaplan-Moss wrote:
> On Fri, Jun 1, 2012 at 10:14 AM, Victor Hooi <victo...@gmail.com> wrote:
>> The reason for my post - is there anything from the Django core as a whole
>> on this? What's the future roadmap like in terms of CBV's? Are there going
>> to be any changes to it, or are we safe to assume things will be as they are
>> now.
>
> I think as a whole we're.... divided. Luke's opinions differ from
> mine, and it's entirely unclear to me who's "right" or even if there's
> a "right" to be had. And that's just the two of us!

I personally found all the responses and discussion really enlightening,
and it moderated my opinions somewhat.

Here are the things I'd like to actually see change:

1) An easy one: Some documentation to the effect of this: "The
Django-supplied CBV base classes may not be the best fit for your
project. Consider two alternatives - use a function, or write your own
base classes."

I'm happy to write that paragraph if others agree.

2) A harder one: nicer functional way of using CBVs in the simple case,
so they can be used from traditional function view without subclassing.
In theory, you can do this:

def my_view(request):
return ListView.as_view(template_name='foo.html')

However, you've got a few problems:

* you can't pass in the extra context you need, which is pretty much a
crucial requirement
* you have some gotchas with things like POST requests.

I found I had to write something like this snippet:

https://gist.github.com/2596285

But it's not ideal in a number of ways, like needing its own
documentation, since it doesn't just set parameters on ListView.


Luke

--
O'REILLY'S LAW OF THE KITCHEN
Cleanliness is next to impossible.

Luke Plant || http://lukeplant.me.uk/

Marc Tamlyn

unread,
Jun 5, 2012, 2:02:14 AM6/5/12
to django-d...@googlegroups.com
There is a plan to do some work on the docs at the djangocon sprints - in particular trying to get some examples of when you 'could' and when you 'should not' use the generic CBVs.

With regards to Zach's point about TDD testing - some of that may simply be familiarity. I don't know about you but it would have been very difficult for me to get into successfully TDDing a functional view until I'd written several dozen views and knew what the pattern is. You can still test the CBV top to bottom, exactly as you would with a function based view. Yes there may be some shift to conventions, but that will come with familiarity.

I think part of the important difference is that when you look at a CBV for the purposes of unit testing it, you feel very quickly that you should be testing the individual methods. This is actually really nice and gives a lot more branch-coverage without rerunning the same 4 database queries every time for variables which aren't used. Without CBVs a complex view can easily extend over 50 or so lines, whereas it's more natural to split this up and test the sections independently with a Class based system. I know in general we should be 'writing less view code' and pushing the logic elsewhere, but that depends on what that logic is - for example the view layer needs to decide whether to return JSON or HTML depending on certain headers in the request, and that is more easily testable as an overridden render to response method than as the last 4 lines of a 50 line view.

Marc

Albert O'Connor

unread,
Jun 5, 2012, 9:05:29 AM6/5/12
to django-d...@googlegroups.com
My feeling is that though some people might have uses for CBV, we
shouldn't be suggesting that developers should prefer CBV to function
based views. When it comes to maintainability, FBV are better, and I
would agree that they are more Pythonic.

When I tried to use CBV, I found the inheritance semantics lead to
unexpected results when composing mixins. I wanted to spend my time
creating web apps and not debugging to figure what 3 lines of glue
code I would have to write in the correct overridden method to make
CBV work for me in my usecase. At the time I felt of have a list of
say context providers would have made more sense than mixins.

If people have uses for CBV, they should be available, but advocating
that more builtin or contrib views should be made class based is
something I would be against personally, unless it really made sense
in a specific use case.

Albert O'Connor
> --
> You received this message because you are subscribed to the Google Groups
> "Django developers" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/django-developers/-/VZsGxxTYyoIJ.
>
> To post to this group, send email to django-d...@googlegroups.com.
> To unsubscribe from this group, send email to
> django-develop...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/django-developers?hl=en.



--
><><><>< Albert O'Connor - amjo...@gmail.com
albertoconnor.ca | wildernesslabs.ca | watpy.ca

Donald Stufft

unread,
Jun 5, 2012, 9:14:14 AM6/5/12
to django-d...@googlegroups.com
On Tuesday, June 5, 2012 at 9:05 AM, Albert O'Connor wrote:
My feeling is that though some people might have uses for CBV, we
shouldn't be suggesting that developers should prefer CBV to function
based views. When it comes to maintainability, FBV are better, and I
would agree that they are more Pythonic.

When I tried to use CBV, I found the inheritance semantics lead to
unexpected results when composing mixins. I wanted to spend my time
creating web apps and not debugging to figure what 3 lines of glue
code I would have to write in the correct overridden method to make
CBV work for me in my usecase. At the time I felt of have a list of
say context providers would have made more sense than mixins.
Don't confuse the current Generic Class Based Views with Class Based
Views in general. In almost every case Class Based Views are a net win,
it's the generic views that are often the incorrect choice (as it makes sense,
if what your view is doing isn't generic, then a Generic view isn't what you need). 

Albert O'Connor

unread,
Jun 5, 2012, 9:29:32 AM6/5/12
to django-d...@googlegroups.com
Class Based View are awesome, except the ones which are built in?

I agree, as has been suggested, that if you make a really flat class
based views like the admin itself, you can gain some benefits, but I
still think those benefits are heavily tied to assumptions one can
make in a specific problem space. Keeping the ability to create a
Class Based View has value, but it is up to to the people who like
them to show the rest of us how they can be used with out creating
more problems then they solve, and just because they exist doesn't
mean they should be used more than they are. Apparently when it comes
to generic class based view they should be used less.

Albert

Zach Mathew

unread,
Jun 5, 2012, 9:55:56 AM6/5/12
to django-d...@googlegroups.com
I'm not suggesting that CBVs make it harder to test (I actually think it should be no different because the tests should avoid being implementation specific). I just feel that the pattern of testing/refactoring is different than the typical TDD approach (one could argue that this is not necessarily a bad thing - but that's a whole another can of worms).

I think Marc makes a very valid point about CBVs being well suited for unit testing. This I agree with. But I typically try to avoid unit testing as much as possible in favour of a more "outside-in" approach (ie. integration testing).

For example, I would avoid unit testing the "get_context_data" method on a CBV and instead have a test that performs a request on the view and tests the context variables.

I'm beginning to think that the divisions on this issue among developers might be tied to development style. This would explain why some people love them and some people hate them.

Donald Stufft

unread,
Jun 5, 2012, 10:12:03 AM6/5/12
to django-d...@googlegroups.com
On Tuesday, June 5, 2012 at 9:29 AM, Albert O'Connor wrote:
Class Based View are awesome, except the ones which are built in?
Both the Built in Generic Class Based Views, and Class Based Views
in general are great. Generic Class Based Views are not awesome when
your view is not generic. 

I agree, as has been suggested, that if you make a really flat class
based views like the admin itself, you can gain some benefits, but I
still think those benefits are heavily tied to assumptions one can
make in a specific problem space. Keeping the ability to create a
Class Based View has value, but it is up to to the people who like
them to show the rest of us how they can be used with out creating
more problems then they solve, and just because they exist doesn't
mean they should be used more than they are. Apparently when it comes
to generic class based view they should be used less.
The typical FBV that i've personally witnessed ends up being one large
chunk of code where it's both impossible to reuse, but slightly differently,
in a way that the original view didn't give you, and impossible to test small
"units" of functionality.

My best guesses as to why most people tend to write this way is because
people like their views to be "one unit". For function based views that unit
is one function and for class based views that unit is one class.

The difference then lies in that within a class it is very easy to have multiple
"sub units" (methods) that can each be dedicated to one purpose, and can
easily be tested independently.

Outside of the testing benefits, you now have a view where you can easily
modify one "sub unit" without having to reach in and rewrite part of the view.

An example would be, with the generic views, it's the pattern to have a
"get_queryset" method which returns the queryset that the view will work off
of. With a simple Mixin of::

    class UserMixin(object):
        user_field_name = "user"
        
        def get_queryset(self, *args, **kwargs):
            qs = super(UserMixin, self).get_queryset(*args, **kwargs)
            qs = qs.filter(**{self.user_field_name: self.request.user if self.request.user.is_authenticated() else None})
            return qs

We now have the ability to "reach" into, and add filtering by the currently logged
in user to any view that uses the get_queryset method in this way. This means
that I could write a view that returns all of the "Widgets" in a system, and by
simply adding this Mixin to the view, create a second view that lists all of
"my" widgets.

In order to do this with FBV's i'd either need to modify the existing FBV to accept
a parameter that says if it should filter by logged in  user or not or copy/paste
the code into a new FBV. These options can be acceptable, especially when you
control the code where those views come from. However if you do not control
that code (if it for instance, comes from Django or comes from an external library)
now you have the ability to really make those kinds of tweaks.

Donald Stufft

unread,
Jun 5, 2012, 10:12:45 AM6/5/12
to django-d...@googlegroups.com
On Tuesday, June 5, 2012 at 9:55 AM, Zach Mathew wrote:
I'm not suggesting that CBVs make it harder to test (I actually think it should be no different because the tests should avoid being implementation specific). I just feel that the pattern of testing/refactoring is different than the typical TDD approach (one could argue that this is not necessarily a bad thing - but that's a whole another can of worms).

I think Marc makes a very valid point about CBVs being well suited for unit testing. This I agree with. But I typically try to avoid unit testing as much as possible in favour of a more "outside-in" approach (ie. integration testing).

For example, I would avoid unit testing the "get_context_data" method on a CBV and instead have a test that performs a request on the view and tests the context variables.
This is going to be slower than just unit testing get_context_data. 

I'm beginning to think that the divisions on this issue among developers might be tied to development style. This would explain why some people love them and some people hate them.



On Tuesday, June 5, 2012 2:02:14 AM UTC-4, Marc Tamlyn wrote:
There is a plan to do some work on the docs at the djangocon sprints - in particular trying to get some examples of when you 'could' and when you 'should not' use the generic CBVs.

With regards to Zach's point about TDD testing - some of that may simply be familiarity. I don't know about you but it would have been very difficult for me to get into successfully TDDing a functional view until I'd written several dozen views and knew what the pattern is. You can still test the CBV top to bottom, exactly as you would with a function based view. Yes there may be some shift to conventions, but that will come with familiarity.

I think part of the important difference is that when you look at a CBV for the purposes of unit testing it, you feel very quickly that you should be testing the individual methods. This is actually really nice and gives a lot more branch-coverage without rerunning the same 4 database queries every time for variables which aren't used. Without CBVs a complex view can easily extend over 50 or so lines, whereas it's more natural to split this up and test the sections independently with a Class based system. I know in general we should be 'writing less view code' and pushing the logic elsewhere, but that depends on what that logic is - for example the view layer needs to decide whether to return JSON or HTML depending on certain headers in the request, and that is more easily testable as an overridden render to response method than as the last 4 lines of a 50 line view.

Marc

--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To view this discussion on the web visit https://groups.google.com/d/msg/django-developers/-/_9hq-OjYc3wJ.

Carl Meyer

unread,
Jun 5, 2012, 10:35:15 AM6/5/12
to django-d...@googlegroups.com


On 06/05/2012 08:12 AM, Donald Stufft wrote:
> In order to do this with FBV's i'd either need to modify the existing
> FBV to accept
> a parameter that says if it should filter by logged in user or not or
> copy/paste
> the code into a new FBV.

Not true, you can also have a function view that returns a
TemplateResponse, and do the same types of tweaks using reusable decorators.

Carl

Donald Stufft

unread,
Jun 5, 2012, 10:46:47 AM6/5/12
to django-d...@googlegroups.com
Maybe in that exact case. You can take the example further and have the same
or another Mixin also handling setting the user field of model instance (which on
a tangent, is one of the places Generic CBV's can improve imo). So now you can
Mixin automatically setting the ``user`` field of a Model to the currently logged in user.

You could also be calling an external API, and want to pass additional data to that
API in this instance of the view, TemplateResponse won't help you and the original
options stand here where you either copy/paste the view, or modify the existing
view.

It's pretty much a fact that module level functions in Python are completely unable
to deal with any modification to internal logic without building up a list of kwargs/flags
that they accept. Even if you are forward thinking and break your FBV's into multiple
sub functions that the actual view calls, you cannot modify how it calls those functions,
or swap out which functions it calls without getting into hacky monkey patching or copy
and pasting things.

Carl

Zach Mathew

unread,
Jun 5, 2012, 11:08:46 AM6/5/12
to django-d...@googlegroups.com

On Tuesday, June 5, 2012 10:12:45 AM UTC-4, dstufft wrote:
On Tuesday, June 5, 2012 at 9:55 AM, Zach Mathew wrote:
For example, I would avoid unit testing the "get_context_data" method on a CBV and instead have a test that performs a request on the view and tests the context variables.
This is going to be slower than just unit testing get_context_data.

That's a cost I'm willing to accept. The big advantage is that I could completely change the implementation of my view without having to rewrite my tests (ie. the tests are not implementation specific).

We might be getting sidetracked into a debate about testing methodologies, so let me reiterate that the general point I'm trying to make here is just that CBVs might be more suitable for a different style of programming/testing than the tdd top down/outside-in testing approach. And this might be the cause of some people's frustrations with it.
 

Albert O'Connor

unread,
Jun 5, 2012, 11:11:52 AM6/5/12
to django-d...@googlegroups.com
> Both the Built in Generic Class Based Views, and Class Based Views
> in general are great. Generic Class Based Views are not awesome when
> your view is not generic.

My experience is using Generic Class Based Views as an inspiration for
ones own Class Based Views lead to a bad user experience, both for
myself and apparently other people. I think it is worth highlight in
the documentation that Generic Class Based Views are useful, but
apparently not how you should write your own.

Mixing in your UserMixin with other mixins that do additional query
modifications will lead to the writer of code having to create new
mixin which either combines both lines of code into one through
copying or explicitly calling each mixin, which will itself be
additional lines of code.

I can see an argument for using CBV to create library views which are
expected to both be reused and customized extensively, but those CBV
should themselves be flat with a very clear execution model. Using
inheritance to override behaviour with the syndication framework works
because you only have to look at one class to see what behaviour you
are modifying, but it doesn't scale to a any number of mixins, except
many for the one your provide in your distinct use case.

It should be noted a vast majority of views that developers write
which aren't "generic" will never ever be reused and thus probably
should be CBV.

Albert

Donald Stufft

unread,
Jun 5, 2012, 11:33:53 AM6/5/12
to django-d...@googlegroups.com

On Tuesday, June 5, 2012 at 11:11 AM, Albert O'Connor wrote:

Both the Built in Generic Class Based Views, and Class Based Views
in general are great. Generic Class Based Views are not awesome when
your view is not generic.

My experience is using Generic Class Based Views as an inspiration for
ones own Class Based Views lead to a bad user experience, both for
myself and apparently other people. I think it is worth highlight in
the documentation that Generic Class Based Views are useful, but
apparently not how you should write your own.
The GCBV's tried to go very far into reusability, to the point where they
have several layers of indirection to what is going on. Personally I prefer
a case where you have the base view which is well written and contains
all of the "Base" functionality instead of having a base view which
is actually comprised of half 3-6 different Mixins.

However adopting some of their conventions into your own CBV's will
go a long way (get_object, get_queryset etc). 

Mixing in your UserMixin with other mixins that do additional query
modifications will lead to the writer of code having to create new
mixin which either combines both lines of code into one through
copying or explicitly calling each mixin, which will itself be
additional lines of code.
This is only true if you write poor mixins. 

I can see an argument for using CBV to create library views which are
expected to both be reused and customized extensively, but those CBV
should themselves be flat with a very clear execution model. Using
inheritance to override behaviour with the syndication framework works
because you only have to look at one class to see what behaviour you
are modifying, but it doesn't scale to a any number of mixins, except
many for the one your provide in your distinct use case.

It should be noted a vast majority of views that developers write
which aren't "generic" will never ever be reused and thus probably
should be CBV.
I assume you meant shouldn't be here. There are benefits beyond
the reusability (which the reusability is something I speak a lot about),
in terms of testing, breaking things into easier to digest chunks. Even
the most non-generic view tends to create a good deal of boilerplate.

Even something as simple as the default get() and post() methods
reduces the amount go cognitive overhead needed while parsing
what a view does.

As an example a dummy: https://gist.github.com/2875669

Similar number of lines (intact the CBV is a bit more), however with
the CBV I've broken my view down into smaller chunks which, other
then via self, are not able to affect one another. This allows me to focus
on a much smaller unit of code if I am debugging making me have to
"page" less of the application into my head at once. (As an example,
maybe the post method accidentally reuses a variable from the setup
code that the generic code was expecting to be there).

Even if all you use the CBV's for is a "Namespace to hold crap" I feel
that your code will end up better as it enables you to break apart a view
into smaller and more manageable chunks, without polluting the views.py
namespace with multiple functions for every view.

Albert O'Connor

unread,
Jun 5, 2012, 12:03:23 PM6/5/12
to django-d...@googlegroups.com
I did mean shouldn't, sorry about that.

We seem to have agreement that when it comes to mixins and the depth
of the inheritance hierarchy it easy to go astray, or at least generic
CBV did. From that I would argue it is difficult to write a good
mixin.

I disagree with your digestion line of thinking, because for me the
beauty of Django lies in being able to quickly and explicitly answer
the question what is this view passing into my template. I think that
is more important than knowing what happens when I post to a view
versus get it, which I think is still pretty obvious with FBV. As far
as I can tell CBV makes the latter more explicit while obscuring the
former. It maybe the case that testing is easier with CBV, but I would
argue that debugging FBV is easier. You can also add overhead by
inheriting from an obscure class based view and only implementing
post. From glance a reader won't know what the get does.

I can imagine use cases exist where CBV make sense, but they seem to
be instances where customization and testing are critical which points
me back to library views explicitly meant for reuse, not every day
business logic heavy views.

Albert

Mikhail Korobov

unread,
Jun 5, 2012, 12:42:23 PM6/5/12
to django-d...@googlegroups.com
If you pollute the namespace with small helper functions you can test them independently and use them outside single CBV. This style also helps to write less coupled code - all dependencies are visible (they are all in functions' params list) so this forces developer to rethink the decomposition and write small functions with less arguments (and thus less dependencies) and so such functions are more reusable and it is easier to test them because they need less state information and the output is (or should be) simpler.

This 'library' approach is opposite to 'framework' approach when you're given a class that almost solve your problem and then customize it to make it solve your problem. With 'library' approach you're given small building blocks and use them to implement the necessary logic. 

I think both approaches are useful in different circumstances. We shouldn't say one approach is superior to another. I personally found FBV and 'library' approach to writing views suite my needs better but experience may vary.

-1 for rewriting to CBV for the sake of rewriting; +1 for adding a clear note to docs that FBVs are not deprecated. It seems there is a lot of confusion about this.

вторник, 5 июня 2012 г., 21:33:53 UTC+6 пользователь dstufft написал:
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to
For more options, visit this group at


--
You received this message because you are subscribed to the Google Groups
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to
For more options, visit this group at



--
<><><>< Albert O'Connor - amjo...@gmail.com

--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to django-developers+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.


вторник, 5 июня 2012 г., 21:33:53 UTC+6 пользователь dstufft написал:
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to
For more options, visit this group at


--
You received this message because you are subscribed to the Google Groups
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to
For more options, visit this group at



--
<><><>< Albert O'Connor - amjo...@gmail.com

--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to django-developers+unsubscribe@googlegroups.com.

Xavier Ordoquy

unread,
Jun 6, 2012, 2:45:39 AM6/6/12
to django-d...@googlegroups.com
Hi,

I also had a couple of issues with Django's generic CBV.
My feeling is it raises a lot of frustration because it feels like there isn't much missing.
I've been playing with a few solutions to work around that.

I started a small proof of concept on chaining GCBV and a few other goodies.
I'm a bit reluctant to speak about it because *I'm not happy* with the way it currently is now.
The general idea was to be able to go as far as possible for newcomers without modifications.
To achieve that result, I took example on what forms and models already and used the same thing to chain mixins.

It currently what it looks like is.

1) define the mixins

class ProjectMixin(ObjectMixin):
model = Project
pk_url_kwarg = 'project_id'

def get_queryset(self):
return Project.objects.filter(members=self.request.user.id)

class BugMixin(ObjectMixin):
model = Bug
pk_url_kwarg = 'bug_id'

def get_queryset(self):
return = Bug.objects.filter(project=self.project)


2) define the views

class ProjectView(View):
project = ProjectMixin(default_mode='detail')


class BugView(ProjectView):
projects = ProjectMixin(mode='list')
bug = BugMixin(default_mode='detail')


3) define the urls

urlpatterns = patterns('',
url(r'^projects/$',
ProjectView.as_view(mode='list'),
name='projects'),
url(r'^projects/new/$',
ProjectView.as_view(mode='new'),
name='new-project'),

....
)


A few things to notice.
View can inherit from the others.
Objects are "namespaces" in the view. See I get project (a single object) and projects (list of projects the user is member of) in the BugView.
You define only one view that you can specialize into list, detail, create, update, delete (although delete isn't implemented yet).


The current state for that:
- There's no documentation (as I said, I was a bit reluctant to do that mail because it is still a bit early)
- I recently switched from reusing the django's generic cbv to duplicating them in the code. A few implementation details still need to be cleaned.
- I'm not happy with the way I "specialize" the mixins according to the mode they should be in. I'm currently changing the mixin instance's heritage which I feel is *not* what I should do. I'll probably try to do something similar to what the forms do with BoundField
- I'm not happy with the way the "mode" is set too.
- Paginators have a semi working namespace. They *are* namespaced in the template, but aren't for the url part, this is work in progress.

Please keep that in mind if you have a look at the current code.

The "proof of concept" is there:
https://github.com/linovia/django-alternative-views

I wrote a demo project:
https://github.com/linovia/django-alternative-views/tree/master/demo

Tests should cover most (think it was around 90%) of the custom code. Since the inclusion of django generic cbv, it has droped but I'll see how I can play django's test for that part (not going to rewrite existing tests).


Regards,
Xavier Ordoquy,
Linovia.

Reply all
Reply to author
Forward
0 new messages