
Django Vanilla Views 1.0 released. - tomchristie
http://django-vanilla-views.org/
======
po
Contrary to somewhat popular belief, Django's function-based views are not
deprecated and as far as I know, there are no plans to remove them. Django's
class-based views were introduced and the generic views ported over to the CBV
style (the older FBV versions _were_ deprecated), however after giving it a go
in a small part of our app, I found them to be overly-complex and hard to
extend and went back to FBV.

In my opinion, Django's CBV's are polarizing. Some people really love them as
a way to reuse code (e.g. they are recommended glowingly in the popular Two
Scoops of Django book) and people like me don't. I feel like inheritance is a
poor way of modeling views and reusing code.

Whenever anyone voiced complaint about the CBV system, it usually was mixed in
with complaints about the implementation of the generics. The response was
always, "you don't have to use the generics provided, write your own." I'm
really glad to see that Tom went exactly that route, and I'm happy that Django
as a system is flexible enough to allow it. I may not be 100% convinced just
yet but I'm willing to try this out and it seems like a definite step in the
right direction to me. Nice work.

~~~
misiti3780
I have been looking at them (but not using them) for a while because I cant
see why I would want to re-use a view + it seem s like they require more work
to implement then

if request.method == "POST":

    
    
       return render_request('template.html", params)

~~~
Wilya
The basic concept doesn't make a big difference. The real meat is the generic
model views, not the base CBV, imo.

It may not be revolutionary, but extending an UpdateView to block anonymous
users and throwing a mixin that limit access to the objects the current user
owns, I can have my "edit a blog post" view looking like:

    
    
      class EditBlogPost(OwnedObjectsMixin, AuthenticatedUpdateView):
        model = Blog
        form = BlogForm
    

and all I have left to do is put my template, which is quite nice (especially
when the List, Create, Delete views are about the same length in code).

It gets less useful (and more convoluted) as your views get further away from
basic CRUD stuff, but I still feel it's quite useful.

(Edited: the difference is more clear on the "Update" view)

~~~
thezilch
As opposed to two decorators on the blog module's edit method? I'm not sure a
ClassView grants us any advantages for this use.

    
    
      @is_authenticated
      @is_owner
      def edit(self):
        ...

~~~
Daishiman
The decorator can only add behavior prior to the original function's
execution, and many decorators may not necessarily be applied together. CBVs
allow a composition of mixins that can include behavior that's substantially
more complicated and can deal with any of the methods and members defined for
the view.

A well-defined base CBV allows you to limit the use of RequestContexts, checks
for method types, and special validations. For small projects it may not make
a difference; for projects with at least couple dozen views and a bunch of
common behavior, they increase readability tremendously.

Also, they offer a very good template for defining view behavior. Once you're
familiarized with CBV method definitions it's much easier to grok code, as the
view flow is much more standardized than for regular function views.

------
arocks
This should be the standard. Today, I'd argue that class based generic views
are the most complex part of Django to learn. The concern is usually met with
rather blunt responses like 'read the source code' or 'try harder'.

The goals of having a class based generic view was quite appealing with the
possibility of leveraging inheritance and properties. But Mixins were probably
the wrong way to achieve it. The Method Resolution Order can get very
confusing leading to hard to resolve bugs. It seemed to be a very un-Pythonic
("If the implementation is hard to explain, it's a bad idea") implementation
to me.

~~~
wiremine
> I'd argue that class based generic views are the most complex part of Django
> to learn.

Also, after using them in a few projects, they reduce grokability and
maintainability. Django's ORM is much more complex, but it operates at the
right level of abstraction. CBVs always felt a bit too high level to work
well. Going back and reading CBVs I wrote months ago always took more time
than it feels like it should have.

That said, it took the ORM a while to get right, too, and the Django community
is thoughtful when it comes to abstraction, and I'm sure views will land in a
good spot.

------
tsurantino
I completely disagree with pundits that argue CBVs are way more complicated
than function-based views.

Three key differentiators for me are the reduction in redundancy with CBVs,
consist organization of code and better code reuse through inheritance. This
comes out best with generic model views (as one poster has said).

The real problem with CBV generic view usage is that it's not very well-
documented, specifically the order of method calls. I often have to refer to
the source to understand the flow (which is fine, but a pain, and I imagine
extremely intimidating for new users).

Were this well documented, I think it'd actually be _easier_ for people to get
into Django - because CBVs outline a lot of the key features that people would
use in Django anyways, except now in a much more formal, easy-to-use way
(i.e., get_context_data, Form submission and so forth).

In contrast, function views seem to be more for experts who need to do some
kind of complicated view processing that goes beyond the bounds of a typical
CRUD app.

------
andrewingram
I'll paste my thoughts from a conversations I had with someone about them:

"There are places where the generic views could/should be simplified,
get_template_names and get_form_class are horrendously complicated. But his
big example is removing get_form_kwargs, which is probably my single most
heavily-used function when using them (Django's generic class-based views).
Overriding form_valid is always a little gnarly, because you need to know the
implementation details to know it's not worth calling super."

In general, I'm not sold on Tom's specific implementation, primarily because
it throws away parts of the API that I personally use quite heavily. Of
course, the counter-argument is that he's kept the parts that he uses heavily.
I suspect the ideal solution is somewhere between Tom's implementation and the
existing one.

~~~
tomchristie
Hi Andrew, the migration notes cover the removal of `get_form_kwargs()`.

The simple answer here is that you're actually much better off just overriding
`get_form()`. It's no more complicated, and it's much more direct and obvious.
We can do away with `get_form_kwargs()`, `get_initial()` etc - they're
unnecessarily granular.

> you need to know the implementation details to know it's not worth calling
> super

The simplicity is self re-inforcing here - the implementation is trivial, so
it's easy to figure out how to totally override a method if you want too. Of
course this doesn't prevent you from using a `super` style if you want to.

~~~
andrewingram
There's something about your example that wasn't convincing to me, but I've
tried it out with some of my use cases. Whilst your approach is less DRY, it
does seem to lead to more readable code, so I'm going to look into it further.

We should fork django-extra-views and see what we can come up with.

~~~
tomchristie
> We should fork django-extra-views and see what we can come up with.

Yup, that'd be interesting. Hopefully you've seen my comment to that effect
here: [http://django-vanilla-views.org/topics/django-extra-views-
co...](http://django-vanilla-views.org/topics/django-extra-views-
compatibility)

~~~
andrewingram
A little amusing that the only bits that work are the bits I've been
regretting merging in :)

------
johnthealy3
I started working with Django in 1.3.1 as my first REST framework. When I got
to the views, it was easy to understand how the function responded to an HTTP
request:

if request.POST:

validate

save form

redirect to success page

else if request.GET:

show the form

Learning the views this way was very helpful when I barely understood how the
internet worked. So naturally, when I took on an intern this year, I got her
started with the Django tutorial, then gave her the above pseudocode as an
example of how to write a simple form. After she worked on it for a while and
got very confused, I looked over the Django 1.5 tutorial with her and saw
those awful, overmagicked generic views they use now. I spent an hour trying
to implement what would have taken me two minutes if the views were written
manually, until I gave up and rewrote all of her code while standing on my
soapbox.

Needless to say, I've been hoping for something like this project ever since.

------
blaze33
Django class based views always seemed overly complicated to me. I cope with
it thanks to the useful [http://ccbv.co.uk/](http://ccbv.co.uk/) and
frequently had to hand draw the inheritance tree to understand what the hell
was going on with my method calls.

I'll be curious to know what was the actual reasoning behind this complicated
design.

~~~
tomchristie
I thought the design seemed reasonable at the time, the strict separation of
concerns that the mixin classes provide is valid enough.

It's only now that we've been using CBVs for a while that it's become more
apparent that they're somewhat over-designed, and can be awkward to get to
grips with.

------
badclient
Note to non-regular django devs: a django view is equivalent of the controller
in other frameworks.

~~~
X-Istence
Not the case for Pyramid for example...

------
raverbashing
Interesting

\- Django regular views are ok (though not class based)

\- Django "class views" are a product of brain damage, really (see the example
to see what I mean)

This looks like sane class based views, but I was expecting something more
like the way Pyramid does it (which are not generic, but class based)

~~~
acdha
> Django "class views" are a product of brain damage, really

“Brain damage” is rather harsh: they're following a valid design principle but
(IMO) carried a little further than the scope of the problem might require,
running into the classic tradeoff versus ease of acquisition.

------
tomlu
My experience has been that plain old function based views work out to be
simpler and more flexible, at the cost of a little more duplication. Don't
forget they are an alternative too!

~~~
erichurkman
Plus you can mix and match different view styles. If you have a lot of very
similar views, elevate them to class-based views, or a smarter function-base
view. If you have a lot of dissimilar views, you can keep them in function-
based views while other parts of your app are using Vanilla Views or class-
based views. Mix and match as appropriate (right tool, etc).

------
ensignavenger
I'm working on my first large scale programming project, learning Python and
Django right now. I am in the midst of trying to figure out CBV's, and I am
starting to understand and agree with the criticism of the generics that
commenters have been making. If I want to make any modifications, I am finding
myself just writing my view from scratch. I'm going to give this project a try
today and see if it makes my life easier!

------
Nurdok
I personally don't find the regular CBV to be difficult to use and I prefer
CBV to FBV in 99% of cases. I actually find it _easy_ that the flow is
separated into different methods, so that when I want to change a specific
behavior, I don't have to read the whole view. That being said, I do find that
I have to look at the source code for CBV from time to time, even though the
documentation is quite good - but maybe "looking through source code" isn't
quite as intimidating to me as to more beginner programmers.

------
kanja
I guess I'm in the minority - I really like the class based views for simple
crud work. Obviously function based views are a better fit for things that are
outside of the simple. but I've had a lot of luck using CBV to simplify crud
work.

Interested to try out django vanilla views

------
lunchbox
Side comment: that's a nice website; how did you make it? I see it's hosted on
GitHub pages and that you use Bootstrap. Did you write all the HTML/CSS
yourself, or use Markdown, etc?

~~~
tomchristie
Thanks!

The documentation source is markdown.

The styling and documentation building script is custom, and taken from the
documentation for Django REST framework.

I'd like to build it into a proper markdown docs tool someday if I can find
the time.

~~~
yellottyellott
Dear God, this. I started looking at your makedocs.py over the weekend myself.
I've never liked rst.

------
Siecje
In the example where does the account variable come from in the form_valid
method?

def form_valid(self, form):

    
    
            send_activation_email(self.request.user)
    
    
            account = form.save()

~~~
tomchristie
Hiya, I think you've misread the example. The `account` variable doesn't come
from anywhere outside the method. It's being instantiated right there.

------
bliti
This brings Django one step closer to including scaffolding (like Rails).

~~~
X-Istence
scaffolding doesn't require class based views ...

------
adamc
License isn't open. Pass.

~~~
tomchristie
Uh, whatcha talking about? It's a standard BSD 2-clause license.

[http://opensource.org/licenses/BSD-2-Clause](http://opensource.org/licenses/BSD-2-Clause)

~~~
adamc
Doh. My bad.

~~~
tomchristie
No problem :)

