I spent the last weaks reading documentation (FAQs, installation,
templates, models and so on) and It feels like
I'm in the right path.
One thing the project I was working had and I liked was lots of
decorators on top of controllers (what you people call views - and
makes sense)
Something like that:
#-----------------------------
@require_permission('login')
@expose_xhr('admin/data/index.html', 'admin/data/table.html')
@paginate('media', items=20)
@observable(events.Admin.DataController.index)
def index(self, page=1, search=None, filter=None):
"""
Home page for ... bla bla
"""
filter = Person.query.options(orm.undefer('comment_count'))
tag = ....
return {
'base': self.info,
'search': search,
'search_form': search_form,
'media_filter': filter,
'tag': tag,
}
#-----------------------------
It feels right to make the controller returns only the data to be
rendered/serialized instead of a HTTP response. Not doing that makes
it a lot aware of things it shouldn't be and make it easy to repeat
code.
As I said, I'm new to Django and couldn't find out if it had something
like that by default (Pylons dindn't had much of that though).
The things I found was decorators to check request methods (and that's
also great).
So I started writing myself those decorators, because I was already
used to work with them.
As I was teaching myself to use the framework, I realized that using
decorators that way fits in Django philosophies pretty well:
- The framework should be consistent at all levels -> Using
decorators it's easy do make it work
- Django apps should use as little code as possible -> Views only
return data. Decorators render the data to the user
- Don’t repeat yourself:
- The framework, within reason, should deduce as much as
possible from as little as possible.
That last phrase tells everything I'm trying to explain.
A decorator e.g. `@render('page.html')` could get the output of the
view and render to a template using the request information as
"RequestContext" without the view programmer bothering with calling
something like `render_to_response`.
Another decorator could receive 'json' or 'xml' as argument and grab
an serializer to return HTTP data to a Ajax request using the correct
mimetype to avoid making the programmer remember this kind of
information (or even how to instantiate the serializer class).
Well, these were my thoughts and feel free to think otherwise. I would
appreciate to know if something is being done in this direction.
Sorry for the long post!
Bernardo
Hi Bernardo,
You're not the first person I've seen suggest this approach, and it's
certainly legal Python -- but to me, it feels completely wrong.
Django's contract for a view is simple, and very closely aligned to
it's end purpose -- serving HTTP content. A Django view:
* Accepts a HTTP Request, along with any pre-parsed URL arguments
* Returns a HTTP Response
And that's it. While I can see the appeal of trying to do a classical
MVC "Controller" separation, it just doesn't seem appropriate when
you're dealing with a framework that is 100% focussed on delivering a
very specific type of output.
Having views that return HttpResponse doesn't mean you *can't* perform
good separation of concerns. A well designed view *will* separate the
rendering from the data. It just does it with normal, well-decoupled
functions.
It also doesn't mean that you must return a fully serialized HTTP
Response. Consider the case of TemplateResponse. This is a data
structure that will *eventually* be a fully rendered HTTP response,
but until it is baked, it's just a collection of data. This means your
decorator and middleware stack has ample opportunity to modify the
response before it is served to the client.
Returning HTTPResponse also provides a data formatting constraint that
your approach doesn't have. At each level of Django view, you know
you're going to get a HTTP Response. That means there are certain
predictable fields, structures and so on. If you have a view that
returns "Data" -- what format is that data in? Will that format change
if it's decorated? If so, what will it change into? If I have some
extra functionality that I want to add to your view, how do I build a
decorator so that I know it will always work with your view?
So -- in summary: Nobody will can stop you from taking this sort of
"return data then decorate" approach. You certainly *can* build a
fully functional Django stack that uses this approach. However, I
would personally advise against it.
Yours,
Russ Magee %-)
Russel explained the real reasons of why your proposal doesn't fit so
good in Django.
still, this snippet:
On Mon, Dec 12, 2011 at 7:49 PM, Bernardo <jbv...@gmail.com> wrote:
> - The framework, within reason, should deduce as much as
> possible from as little as possible.
> That last phrase tells everything I'm trying to explain.
for me, is opposed to the "explicit is better than implicit" in the
Zen of Python. not a bad thing on itself, but something to be careful
about. (and, personally, it's a big part of why i like Django so
much better than RoR)
now, thinking a little more on what seems to be good: separating the
'data gathering' part of a view from the presentation part, I think it
should be handled at a slightly different level.
for example, make a (generic) view that simply calls a data gathering
function (which is not a view) and hands the result to a HTML
template, and another (generic) view that calls the same function but
returns a different (XML? JSON? Pickle?) representation.
paired with a middleware and some shortcuts in the urls.py, you can
have nicely separated concerns and DRYness.
--
Javier
> Returning HTTPResponse also provides a data formatting constraint that
> your approach doesn't have. At each level of Django view, you know
> you're going to get a HTTP Response.
Yes, now it makes sense the view working only with HTTP request and
responses and the decorators will only work with some kind of specific
information that will not be the same for each decorator.
Being strict, the view (the decorated function) will always return an
HTTP response, but in another (more abstract) layer... I think I'll
need to find some balance in this technique.
Hi Javier,
> for example, make a (generic) view that simply calls a data gathering
> function (which is not a view) and hands the result to a HTML
> template, and another (generic) view that calls the same function but
> returns a different (XML? JSON? Pickle?) representation.
I don't know if I understand what you're saying but the decorator
approach is working exactly like that but instead of calling these
generic views, I decorate my view with it.
Could you explain me that with a simple snippet?
Regards,
Bernardo
On Dec 13, 12:14 pm, Javier Guerra Giraldez <jav...@guerrag.com>
wrote:
I am a complete newbie in the world of webapps, but exactly this was the
reason why I left Flask. Nothing against them, but
@app.route("/")
def hello():
return "Hello World!"
looks to me like a wrong to do things and yes “explicit is better than
implicit” (or “No magic allowed!”) was something I was thinking about.
What I liked about the first look at Django was that it looks just like
a Python app not playing any tricks on me.
Now I have to overcome this feeling with ORMs (be it the Django one or
SQLAlchemy) ... but there is probably not a better way how to do this.
Just my €0.02
Matěj
And the other advantage of Django is that you are not forced to use
the ORM for queries; you could just write everything as plain old
SQL... if you were sure that was the best way to do it!
That's not what I want to do. I like how views are handled, but I
wanted a easier way to render data from multiple return points in a
same function without calling another thing multiple times...
> Now I have to overcome this feeling with ORMs
ORMs are great. I've already spent too many years writing SQL by hand
and I regret the time I lost.
Regards
Bernardo
but I
wanted a easier way to render data from multiple return points in a
same function without calling another thing multiple times...
Earlier today I saw a blog talking about that. I haven't read
everything, but seems that it is what I want.
I still need to see how to combine multiple Class based views to treat
my data.
Thanks!
Bernardo
I still need to see how to combine multiple Class based views to treat
my data.