Alternatives to CBVs (class based views)

121 views
Skip to first unread message

Cal Leeming [Simplicity Media Ltd]

unread,
Sep 12, 2012, 12:58:41 PM9/12/12
to django...@googlegroups.com
Hi all,

There is a lot of debate on whether there is a real future for the Django CBVs (class based views). Personally, I find them tedious, and just wanted a way to keep my views clean.

So, here is a really minimalistic way of having class based views, without the fuss.

This is a fork from:


My thanks to eallik for his initial post on stackoverflow for this.

Personally I think Django's CBVs should offer a really minimalistic base like this, as well as the existing CBV stuff already in the core - so as to not force people into needing to learn an entirely new way of doing things, but at the same time allowing them to reap some of the benefits of using callable classes as views.

Any thoughts?

Cal

Javier Guerra Giraldez

unread,
Sep 12, 2012, 2:44:10 PM9/12/12
to django...@googlegroups.com
On Wed, Sep 12, 2012 at 11:58 AM, Cal Leeming [Simplicity Media Ltd]
<cal.l...@simplicitymedialtd.co.uk> wrote:
> So, here is a really minimalistic way of having class based views, without
> the fuss.
>
> http://djangosnippets.org/snippets/2814/

looks nice. i like that it respects the idea that views in Django are
just callables that take a reques (plus optional extra params) and
return a response. to get inheritance, just make callable objects and
spread functionality as desired.

the generic view functions are good for prototyping, but soon you have
to replace with your own, which is not difficult. the problem with
generic CBV is that they try to factorize every feature so thinly that
the inheritance becomes an unholy mess. any simplification would
either reduce functionality, or make some features harder to replace,
so there doesn't seem to be a way out... apart from not using them.

--
Javier

Cal Leeming [Simplicity Media Ltd]

unread,
Sep 12, 2012, 3:13:30 PM9/12/12
to django...@googlegroups.com
On Wed, Sep 12, 2012 at 7:44 PM, Javier Guerra Giraldez <jav...@guerrag.com> wrote:
On Wed, Sep 12, 2012 at 11:58 AM, Cal Leeming [Simplicity Media Ltd]
<cal.l...@simplicitymedialtd.co.uk> wrote:
> So, here is a really minimalistic way of having class based views, without
> the fuss.
>
> http://djangosnippets.org/snippets/2814/

looks nice.  i like that it respects the idea that views in Django are
just callables that take a reques (plus optional extra params) and
return a response.  to get inheritance, just make callable objects and
spread functionality as desired.

Yeah I was really pleased when I found the original snippet, and this approach can be extended on so easily too.
 

the generic view functions are good for prototyping, but soon you have
to replace with your own, which is not difficult.  the problem with
generic CBV is that they try to factorize every feature so thinly that
the inheritance becomes an unholy mess.  any simplification would
either reduce functionality, or make some features harder to replace,
so there doesn't seem to be a way out... apart from not using them.

Agreed, the CBVs in Django leave me with the same taste that django-tastypie left in my mouth - making a very simple thing overly complex.

This is why I'm wondering if the way forward is to offer two types of CBV, one using the current CBVs in Django, and one using an approach like this.


--
Javier

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


Melvyn Sopacua

unread,
Sep 12, 2012, 4:22:30 PM9/12/12
to django...@googlegroups.com


Op 12 sep. 2012 18:58 schreef "Cal Leeming [Simplicity Media Ltd]" <cal.l...@simplicitymedialtd.co.uk> het volgende:


>
> Hi all,
>
> There is a lot of debate on whether there is a real future for the Django CBVs (class based views).

..snip..
>
> Any thoughts?
>

I understand what you're getting at and agree in principle, but you're not exactly feature compatible.  ;-)

Kurtis

unread,
Sep 12, 2012, 7:11:59 PM9/12/12
to django...@googlegroups.com
I guess I'm the only one who loves Django's CBVs :(
Maybe some good documentation / third-party tutorial is in order? haha

Thanks for sharing though, Cal!

Matt Schinckel

unread,
Sep 12, 2012, 8:34:41 PM9/12/12
to django...@googlegroups.com
One really small nitpick: when returning a 405, it is a requirement that you return a header with the acceptable methods:

> 10.4.6 405 Method Not Allowed

> The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. The response MUST include an Allow header containing a list of valid methods for the requested resource.

(From http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html).


Cal Leeming [Simplicity Media Ltd]

unread,
Sep 13, 2012, 5:32:07 AM9/13/12
to django...@googlegroups.com
Ah, thanks for letting me know - the original snippet by eallik had support for this, but I must have stripped it out not realising.

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

Dan Gentry

unread,
Sep 13, 2012, 7:48:23 AM9/13/12
to django...@googlegroups.com
It would be helpful to see some more complex examples with these classes.  One thing I like about the CBVs is that they include all of the necessary code for common functions.  I have used them extensively (once I figured them out).

Russell Keith-Magee

unread,
Sep 13, 2012, 7:12:43 PM9/13/12
to django...@googlegroups.com
On Thu, Sep 13, 2012 at 12:58 AM, Cal Leeming [Simplicity Media Ltd]
<cal.l...@simplicitymedialtd.co.uk> wrote:
> Hi all,
>
> There is a lot of debate on whether there is a real future for the Django
> CBVs (class based views).

Sigh.

No - there isn't *any* debate about the future of CBVs. There *are* a
lot of people who apparently don't like them who keep making a lot of
noise. Every single time I've spoken with one of those people at
length, the problem has reduced to either:

1) I don't like classes/OO. There's no winning these people over.

2) CBV's aren't documented well. You won't get any argument from me
on (2). I'll take the hit for that -- the initial documentation for
CBVs was my doing, and it has lots of room for improvement.

I'm not aware of anyone in the core that has advocated removing
class-based views from Django.

> Personally, I find them tedious, and just wanted a
> way to keep my views clean.
>
> So, here is a really minimalistic way of having class based views, without
> the fuss.
>
> http://djangosnippets.org/snippets/2814/
>
> This is a fork from:
>
> http://stackoverflow.com/questions/742/class-views-in-django
> http://djangosnippets.org/snippets/2041/
>
> My thanks to eallik for his initial post on stackoverflow for this.
>
> Personally I think Django's CBVs should offer a really minimalistic base
> like this, as well as the existing CBV stuff already in the core - so as to
> not force people into needing to learn an entirely new way of doing things,
> but at the same time allowing them to reap some of the benefits of using
> callable classes as views.
>
> Any thoughts?

What you've described -- a single entry point class-based view base
class -- *does* exist. It's called django.views.generic.View. Override
the "dispatch" method, or write a "get/post/put/etc" method, and
you've got a class-based view.

I also think you should read the discussions that led to the current
form of Class-based views. The pattern you've proposed from Stack
Overflow was one of many suggestions that were made, and were rejected
because of inherent problems with the approach. The discussions are
summarised in the wiki:

https://code.djangoproject.com/wiki/ClassBasedViews

Yours,
Russ Magee %-)

Cal Leeming [Simplicity Media Ltd]

unread,
Sep 14, 2012, 5:16:10 AM9/14/12
to django...@googlegroups.com
On Fri, Sep 14, 2012 at 12:12 AM, Russell Keith-Magee <rus...@keith-magee.com> wrote:
On Thu, Sep 13, 2012 at 12:58 AM, Cal Leeming [Simplicity Media Ltd]
<cal.l...@simplicitymedialtd.co.uk> wrote:
> Hi all,
>
> There is a lot of debate on whether there is a real future for the Django
> CBVs (class based views).

Sigh.

Thank you for the detailed response on this - hopefully this thread will serve as a reference point for people in the future
 

No - there isn't *any* debate about the future of CBVs. There *are* a
lot of people who apparently don't like them who keep making a lot of
noise. Every single time I've spoken with one of those people at
length, the problem has reduced to either:

 1) I don't like classes/OO. There's no winning these people over. 

Well that's certainly not the reason I dislike them - OO makes views tidier, simple.


 2) CBV's aren't documented well. You won't get any argument from me
on (2). I'll take the hit for that -- the initial documentation for
CBVs was my doing, and it has lots of room for improvement.

+1

 

I'm not aware of anyone in the core that has advocated removing
class-based views from Django.  

> Personally, I find them tedious, and just wanted a
> way to keep my views clean.
>
> So, here is a really minimalistic way of having class based views, without
> the fuss.
>
> http://djangosnippets.org/snippets/2814/
>
> This is a fork from:
>
> http://stackoverflow.com/questions/742/class-views-in-django
> http://djangosnippets.org/snippets/2041/
>
> My thanks to eallik for his initial post on stackoverflow for this.
>
> Personally I think Django's CBVs should offer a really minimalistic base
> like this, as well as the existing CBV stuff already in the core - so as to
> not force people into needing to learn an entirely new way of doing things,
> but at the same time allowing them to reap some of the benefits of using
> callable classes as views.
>
> Any thoughts?

What you've described -- a single entry point class-based view base
class -- *does* exist. It's called django.views.generic.View. Override
the "dispatch" method, or write a "get/post/put/etc" method, and
you've got a class-based view.

I noticed this yesterday whilst trawling through the documentation again, so I will look at this again.
 

I also think you should read the discussions that led to the current
form of Class-based views. The pattern you've proposed from Stack
Overflow was one of many suggestions that were made, and were rejected
because of inherent problems with the approach. The discussions are
summarised in the wiki:

https://code.djangoproject.com/wiki/ClassBasedViews

Thanks for sending this link through, looks very detailed, I will spend an hour or two reading through it all and put some thoughts back.
 


Yours,
Russ Magee %-)


--
You received this message because you are subscribed to the Google Groups "Django users" group.

Cal Leeming [Simplicity Media Ltd]

unread,
Sep 18, 2012, 7:24:20 AM9/18/12
to django...@googlegroups.com
Russell,

On a separate note, I am curious about these 'copy-on-call' leaks, and I have not seen this behaviour documented anywhere else.

"The abstraction of the copy-on-call can leak in surprising ways. Some users will try to set up state using an __init__ method (common practice). If any of the state they attach to self in __init__ is mutable (list, dict, object, etc) and they mutate it in the view, this will fail (but not immediately, or in obvious ways)."

Could you elaborate further on this, possibly with a rough example?

Not arguing that CBV approach should be changed, but this copy-on-call behaviour is quite unexpected, no?

Cal

Russell Keith-Magee

unread,
Sep 18, 2012, 7:45:58 PM9/18/12
to django...@googlegroups.com
On Tue, Sep 18, 2012 at 7:24 PM, Cal Leeming [Simplicity Media Ltd]
<cal.l...@simplicitymedialtd.co.uk> wrote:
> Russell,
>
> On a separate note, I am curious about these 'copy-on-call' leaks, and I
> have not seen this behaviour documented anywhere else.
>
> "The abstraction of the copy-on-call can leak in surprising ways. Some users
> will try to set up state using an __init__ method (common practice). If any
> of the state they attach to self in __init__ is mutable (list, dict, object,
> etc) and they mutate it in the view, this will fail (but not immediately, or
> in obvious ways)."
>
> Could you elaborate further on this, possibly with a rough example?
>
> Not arguing that CBV approach should be changed, but this copy-on-call
> behaviour is quite unexpected, no?

The issue is the shallow copy.

You create a view that sets up state in the __init__ method. Part of
your view's state is held in a mutable object (e.g., a dict, list or
object). The __call__ creates a shallow copy of the view object. A
shallow copy of a mutable object copies the container, but the new
container points to the old content.

So, if your view logic modifies something held by the mutable object
(which will be a fairly common occurrence), the modification will be
shared by all instances of your view. Hilarity ensues :-)

You could work around this by using a deep copy, but then you're into
territory where accessing a view could be an incredibly expensive
operation, which is something we want to avoid. It also means anything
you attach to a view must be deep-copyable, which won't always be
true.

Yours,
Russ Magee %-)

Cal Leeming [Simplicity Media Ltd]

unread,
Sep 19, 2012, 6:42:25 AM9/19/12
to django...@googlegroups.com
Thanks for clarifying, I see where my initial confusion was now.

The reason this leak hadn't affected our apps was because we didn't use __init__ to set up the view, instead all the state logic was placed into __call__. Never the less, having a class call return a HTTPResponse will break class usage expectations (as mentioned in the wiki), so this still wouldn't be the cleanest approach.

I think the majority of users seem to be put off by the complexity of using ListView/TemplateView, and not the actual class usage itself. If the documentation highlighted that there was a basic View() object available, it would make the learning curve a bit easier. 

Russell - Would you have any objection to me submitting a documentation patch (https://docs.djangoproject.com/en/1.4/topics/class-based-views/) which shows a basic example of how to use the View() class directly?

Cal


Yours,
Russ Magee %-)

Russell Keith-Magee

unread,
Sep 19, 2012, 6:59:02 PM9/19/12
to django...@googlegroups.com
On Wed, Sep 19, 2012 at 6:42 PM, Cal Leeming [Simplicity Media Ltd]
<cal.l...@simplicitymedialtd.co.uk> wrote:
> Thanks for clarifying, I see where my initial confusion was now.
>
> The reason this leak hadn't affected our apps was because we didn't use
> __init__ to set up the view, instead all the state logic was placed into
> __call__. Never the less, having a class call return a HTTPResponse will
> break class usage expectations (as mentioned in the wiki), so this still
> wouldn't be the cleanest approach.
>
> I think the majority of users seem to be put off by the complexity of using
> ListView/TemplateView, and not the actual class usage itself. If the
> documentation highlighted that there was a basic View() object available, it
> would make the learning curve a bit easier.
>
> Russell - Would you have any objection to me submitting a documentation
> patch (https://docs.djangoproject.com/en/1.4/topics/class-based-views/)
> which shows a basic example of how to use the View() class directly?

No objection at all. As I said in my original reply, the biggest
problem with CBVs is the documentation - something that is my
responsibility. Someone (ahem) needs to do a pretty serious rework
(or, at least, expansion) of the CBV documentation to point out all
the things that aren't obvious.

Danny Greenfeld was taking a look at some of these problems recently,
as were a couple of people at the recent PyCon AU and DjangoCon US
sprints, so if you want to dig into this, check the tickets before you
start serious drafting.

Yours,
Russ Magee %-)
Reply all
Reply to author
Forward
0 new messages