I've got one big what's-the-design-decision/reason question regarding
django 1.3's new class based views: why does django encourage a
hand-crafted context dictionary instead of "just" passing the view
object along?
In zope/plone, I was used to having the view object available in the
template as 'view'. The django equivalent would be to pass a context of
{'view': self} to the template.
All the attributes on the view class (well, object) would be available.
Django prefers the template to stay simple and stupid: what could be
better than encouraging to just add extra methods to the class if you
want something special? Now you have to add the method *and* pass it
along in the dictionary. Double work?
Passing the view object to the template by default seems to me to be an
absolute no-brainer. Class based views ought to mean you get the view
object in your template, right? But Django doesn't do it. So... is there
a specific reason for it?
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"
I think it's the worst part of using Django. Having to manage a
context dictionary in every view is weak.
> Now you have to add the method *and* pass it along in the
> dictionary. Double work?
It is double the work, no doubt about it. Not to mention on
complicated views the context dictionary gets quite long. At that
point I usually just package everything up as a single entry.
--
Greg Donald
Planning for designers to work in code is an extreme edge case. In 15
years of web development I've never once worked with a single designer
who was interested in touching any code. As far as my own web
projects go, the designer is done the moment they give me a layered
.psd.
> Django requires the developer to
> create a simple context dictionary for designers to understand.
How is something like {{ view.myvar }} any harder than {{ myvar }} for
those two designers in the whole world who actually want to touch the
code?
--
Greg Donald
This isn't an especially strong argument against including the view in
the template -- after all, the template language allows dot notation
to explore object attributes. The underlying type is completely opaque
from a template designer's perspective.
Yours,
Russ Magee %-)
To the best of my knowledge, the only reason the view isn't included
in the template context is because over more than two years of design
discussion, I don't think the idea of including the view in the
context was ever proposed.
It seems like a reasonable idea to me, though, and it should be
possible to accommodate in a backwards compatible fashion. The trivial
fix would be to add a 'view' variable to the default context. It might
also be possible to replace the default get_context_data
implementation with something that reflects the attributes of the view
object itself -- however, this will obviously require a bit more
design work to make sure there aren't any backwards incompatible
implications.
Patches welcome ;-)
Yours,
Russ Magee %-)
I haven't got a patch (yet), but I at least created a ticket for it:
https://code.djangoproject.com/ticket/16744
On 09/02/2011 01:01 AM, Greg Donald wrote:
> Planning for designers to work in code is an extreme edge case. In 15
> years of web development I've never once worked with a single designer
> who was interested in touching any code. As far as my own web
> projects go, the designer is done the moment they give me a layered
> .psd.
Please be careful with the unwarranted generalizations based on your
personal experience. I'm sure there are designers who never go beyond
the PSD, but my personal experience happens to be the opposite - I've
never worked with a web designer who didn't handle all of the HTML, CSS,
and templates themselves; almost all of the designers I know are
perfectly competent in front-end coding (and some in Python, too). It
seems a bit rude to dismiss them all as an "extreme edge case." If you'd
like to broaden your horizons, I'd be happy to recommend some names ;-)
> How is something like {{ view.myvar }} any harder than {{ myvar }} for
> those two designers in the whole world who actually want to touch the
> code?
I agree that {{ view.myvar }} is just fine.
But please lay off the overblown rhetoric. I can name fifteen designers
who code off the top of my head (more than I could name who don't).
Carl
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAk5hBdwACgkQ8W4rlRKtE2dmjACfT9EURJhvwTLW/S21ak7TzXvI
U84AoMzbnDACXDf0oTVjtovcen+ybv+6
=Sz6+
-----END PGP SIGNATURE-----
Clearly you've been working with some hybrid wanna-be designers who
probably don't do any heavy lifting in either realm.
--
Greg Donald
Greg, I hope and am going to assume you're joking. If not -- and
remember with email it can hard to tell -- this comes across as
super-insulting.
Either way, you guys are way off topic at this point. Take it to
private email, please.
Jacob
> Passing the view object to the template by default seems to me to be an
> absolute no-brainer. Class based views ought to mean you get the view
> object in your template, right? But Django doesn't do it. So... is there
> a specific reason for it?
Like Russell, I'd never thought of this idea before. The main argument I
can think of against doing this is that it encodes an implementation
detail into your templates. A template shouldn't know whether the data
has come from a CBV or function, and shouldn't have to be changed if you
go from one to the other or back again (both transitions being sensible
in some circumstances). To me, this change would produce very strong
coupling between the presentation logic and the view that produced it.
The history of CBVs in Django is that they are simply a way of using OOP
and inheritance to reduce duplication between view functions and allow
better re-use. They are supposed to be drop in replacements for function
based views in terms of the end result, rather than produce any change
in what a template will contain. This means that CBVs and function based
views are both first class citizens in Django world, and I for one
prefer it that way.
Slight digression: I do not think that CBVs are obvious winners for
writing views. There are significant trade-offs and downsides, such as
ravioli code, as I've blogged about before [1]. I've recently written an
app from scratch using CBVs heavily, and it worked well, but 1) there
were still times that functions were better, 2) there were some
inheritance problems that required a small amount of fairly heavy-duty
metaclass hackery to solve, 3) the code is less transparent to a newcomer.
Regards,
Luke
[1] http://lukeplant.me.uk/blog/posts/class-based-views-and-dry-ravioli/
--
"Doubt: In the battle between you and the world, bet on the world."
(despair.com)
Luke Plant || http://lukeplant.me.uk/
Ok, when you want to keep the function and class based views more or
less the same, the current implementation makes sense.
On the other hand, from an object oriented viewpoint, the class based
views seem to be pretty powerless and non-object-oriented. To me, it
almost seems like they're artificially "castrated" to make function
views look good :-) That's probably not the intention, but...
Probably the best illustration of my point: .get_context_data() should
return a dictionary. And .render_to_response() needs the output of that.
"So" you have to pass the output of .get_context_data() to
.render_to_response(). Wait a minute... We're talking object orientation
here! Why doesn't .render_to_response() call .get_context_data()? This
is just function-like behaviour in a thin object oriented shell.
From an OO viewpoint, I'd rather expect a "self.context = {}" in the
most top-level view baseclass's __init__(). Not passing along a variable
that is calculated in the very same class as a parameter to a method in
that very same class.
Your point that, effectively, {{ view.something }} is different than {{
something}} is valid, though. In that sense, a class based view that
passes {'view': self} as the context dict isn't a drop-in replacement.
Would you be more happy with a more magical view that would inject
everything from local() into the context dictionary or something like that?
Ehm, the current classes based views are pretty good, apart from the
view-not-in-context problem that I see.
That's the one point on which I find those CBV's to be somewhat powerless.
Upon re-reading it sounded a bit like I think the whole of class based
views is powerless and bad, but that was *totally* not my intention :-)
I love 'em :-)
It is already more elaborate than what I'm using locally now :-) I don't
have a proxy object in my own views. Seems like a good idea, though.
Addition: disallow attributes/methods starting with an underscore?
That's a handy way to stow away dangerous methods should you have them
in your view.
The only way I can see yourself shooting in the foot is when you have a
form view that reacts to get() and post(). Upon "get()", the template
*could* call data-modifying methods on the class.
Addition: disallow attributes/methods starting with an underscore?That's a handy way to stow away dangerous methods should you have them
in your view.
> The only way I can see yourself shooting in the foot is when you have a
> form view that reacts to get() and post(). Upon "get()", the template> *could* call data-modifying methods on the class.
I love it when problems solve themselves :-)
On 12-09-11 18:25, Florian Apolloner wrote:I love it when problems solve themselves :-)
On Monday, September 12, 2011 5:39:03 PM UTC+2, Reinout van Rees wrote:
Addition: disallow attributes/methods starting with an underscore?
That's a handy way to stow away dangerous methods should you have them
in your view.
That's already the case for resolving variables in templates, I don't
think we need any specialcasing here.
> The only way I can see yourself shooting in the foot is
when you have a
> form view that reacts to get() and post(). Upon "get()",
the template
> *could* call data-modifying methods on the class.
Not easily, since the templates can only call methods which don't
require extra params, get/post do take request at least.
There's not really anything useful you can do with as_view in your
template, should you attempt it. I also don't think you can do anything
destructive with it.
So it sounds like we don't need the proxy. Good that you added it anyway
as it helps us dig deeper into the problem :-) Luckily it seems we don't
have to dig very deep.
> On 13-09-11 20:33, Tobias McNulty wrote:
>> I love it when problems solve themselves :-)
>>
>>
>> That's a good point. Are there *any* methods in the CBVs that don't
>> take arguments, that also modify data? The only one that I found
>> in the
>> list I'd initially proposed that can be called without arguments is
>> as_view(), and I'm not sure that really even needs protection. Maybe
>> there's no need to protect anything with alters_data / proxying?
>
> There's not really anything useful you can do with as_view in your
> template, should you attempt it. I also don't think you can do
> anything destructive with it.
as_view() is a classonlymethod, which gives an AttributeError when
called on an instance, so putting an instance of the cbv in the
context seems fine for as far as this is concerned.