web2py equivalent of Django's middleware, inverse url mapping

79 views
Skip to first unread message

Stefano

unread,
May 27, 2008, 10:00:12 AM5/27/08
to web2py Web Framework
Hi there,
I came from django and so far I've been quite liking web2py . (the
only think I really don't like is its name: Gluon was way cooler than
web2py :-) ).

I am trying to understand how to do things I used to do in django, in
w2p. To be more specific:
- is there a way to set up something like django "middleware" I mean
something that happens always before the controller processing or
always after it (before the output goes to browser).
- is there a way to define some function / variable visible in every
controller? And in every template?
- does w2p has the equivalent of reverse_url mapping?

I'm experimenting GAE, and so far I think w2p it's the best tool for
the job. Good work!

Later,
Stefano

Massimo Di Pierro

unread,
May 27, 2008, 11:43:42 AM5/27/08
to web...@googlegroups.com
Hi Stefano,

thanks for your comments. Please find the answers below:

> - is there a way to set up something like django "middleware" I mean
> something that happens always before the controller processing or
> always after it (before the output goes to browser).

There are two mechanism to do this, the wsgi way and the web2py way.
The wsgi way consists of inserting a wsgi app in between the web
server and web2py gluon/main.py/wsgibase. Where you do this depends
on the web server that you use.

The web2py ways is the following: any code in model files is executed
before any controller function. Any code in a controller outside
functions is executed before any function in that controller.

Of course you can also use decorators:

def before_and_after(f):
# do whatever you want before
d=f()
# do whatever you want after
return d

@before_and_after
def index(): return dict(message="hello world")

> - is there a way to define some function / variable visible in every
> controller? And in every template?

Anything defined in a model file is visible to all controllers and
all templates. Mind that models are executed in alphabetical order.

> - does w2p has the equivalent of reverse_url mapping?

Yes.
http://mdp.cti.depaul.edu/AlterEgo/default/show/67
http://mdp.cti.depaul.edu/AlterEgo/default/show/42

> I'm experimenting GAE, and so far I think w2p it's the best tool for
> the job. Good work!
>

I agree. :-)

Massimo Di Pierro

unread,
May 27, 2008, 11:49:17 AM5/27/08
to web...@googlegroups.com
ERRATA the validator example should have been

> def before_and_after(f):
> def __tmp__():


> # do whatever you want before
> d=f()
> # do whatever you want after
> return d

> return __tmp__


>
> @before_and_after
> def index(): return dict(message="hello world")
>

Stefano

unread,
May 27, 2008, 12:24:54 PM5/27/08
to web...@googlegroups.com
On Tue, May 27, 2008 at 5:43 PM, Massimo Di Pierro <mdip...@cs.depaul.edu> wrote:

Thanks for your reply, now it is clear to me how to solve the first 2 questions.
My question was not well put, I'm sorry. I mean the reverse mapping of urls, to be used in templates instead of the hard-links; for example (in django):

in urls.py you can define some mapping, with a name attached to them:
[...]
    (r'^projects/', include('ll.prj.urls')),
    url(r'^exporting/feed/(?P<url>.*)/$','django.contrib.syndication.views.feed',{'feed_dict':feeds}, name="feed"),

in prj/urls.py:
[...]
    url(r'^insert_project/$', 'll.prj.views.insert_project_step1',name="insert_project"),
    url(r'^some/where/listing/(?P<page>\d+)/$', 'll.ads.views.show_ads',name="paged_projects"),

in templates you can use those names to do reverse-mapping:
    {{ url insert_project }} [renders to /projects/insert_project/ ]

    {{ url feed category }} [if category = news: renders to /exporting/feed/news/ ]
 
    {{ url paged_listing page_no }} [if page_no = 5: renders to /projects/some/where/listing/5 ]

I mean, is there a way to abstract urls in templates, so that you can avoid to go hunting hand-crafted urls through templates if a url mapping should change after you defined it and used all around? (DRY Principle) I can't find anything similar in the documentation, but I think this feature shouldn't be too hard to add. I'll try to wrap my head around it and see if I came up with a (retrocompatible) way to accomplish this.

Thanks again,
  Stefano

--
~
~
:wq

Chris Leonello

unread,
May 27, 2008, 2:34:21 PM5/27/08
to web2py Web Framework
Hi Massimo,

> Anything defined in a model file is visible to all controllers and
> all templates. Mind that models are executed in alphabetical order.

I use this fact to keep sitewide "helper" functions that are used in
views and controllers in a file in the models directory. This would
be the web2py way? Is it expected that the models directory will only
contain database models?

On May 27, 11:43 am, Massimo Di Pierro <mdipie...@cs.depaul.edu>
wrote:
> Yes.http://mdp.cti.depaul.edu/AlterEgo/default/show/67http://mdp.cti.depaul.edu/AlterEgo/default/show/42

mdipierro

unread,
May 27, 2008, 4:21:39 PM5/27/08
to web2py Web Framework
I do the same. I just call the files helpers_*.py and store them under
models.
> > Yes.http://mdp.cti.depaul.edu/AlterEgo/default/show/67http://mdp.cti.depa...

Stefano

unread,
May 27, 2008, 7:36:34 PM5/27/08
to web...@googlegroups.com
Hello, I took a deeper look into the workings of routes_* and now I realize that the django reverse-map functionality can be obtained just by using routes_out and the diligently generating all the links with the URL() helper.
This is good! (And bad of me to not have seen it before.)

One think I was wondering is: wouldn't it be more logical if every entry in routes_out was automatically added to the substitutions performed in filter_e() function in routes, generating a correspondent routes_in ?

If I show my user a shorter/nicer URL instead of the "usual" ones, I'm pretty sure I'd like that URL to work when my user clicks it.

As things are now I need to have something like this in my routes.py :

routes_in = (
    ('^.*:/short', '/myapp/mycontroller/myfunction$'),
)
routes_out = (
    ('^/myapp/mycontroller/myfunction$', '/short'),
)

Isn't the routes_in entry redundant?

While tampering around I also noticed that is *not* very convenient to use routes: you need to stop/restart your entire server every time you add/edit any route, and there is only one file per server to store'em all. I think it that every application should have its own route file, and route informations should be updated every time the files are changed... But I suppose, by reading your many warnings you put in the docs, that routes.py use is not encouraged, so maybe this functionality is kept purposefully basic. :-)

Anyway, the more I look at w2p, the more I like it.
  S
--
~
~
:wq

mdipierro

unread,
May 28, 2008, 1:22:04 AM5/28/08
to web2py Web Framework
> Isn't the routes_in entry redundant?
you can do

routes_in = []
routes_out = [
('^/myapp/mycontroller/myfunction$', '/short'),
]
for item in routes_out: routes_in.append((item[1],item[0]))

> But I suppose, by reading your many warnings you put in the docs, that routes.py
> use is not encouraged, so maybe this functionality is
> kept purposefully basic. :-)

That is true. I think rewriting URL is dangerous. I was very reluctant
to even add routes.py.

Massimo Di Pierro

unread,
May 30, 2008, 11:12:01 PM5/30/08
to web...@googlegroups.com
Not sure I fully understand but, as a general rule, you should always use the URL function to generate urls. In a view for example

{{=URL(r=request,c='static',f=myfile.jpg')}}

The output of URL is automatically filtered using routes_out. 
Reply all
Reply to author
Forward
0 new messages