new URL router use cases

564 views
Skip to first unread message

Jonathan Lundell

unread,
Feb 16, 2011, 4:38:54 PM2/16/11
to web...@googlegroups.com
[I'm reposting this message from a while back, because the new release 1.92.1 contains it for the first time. It describes some simple use cases for the new URL router. Note that there are still some things that you'll need the existing regex-based router for, but for most cases the new one should work and be easier to configure.]


Suppose you've written an app, named it 'myapp', and want to make it the default, with its name always removed. Your default controller is still 'default', and you want to remove its name from user-visible URLs as well. Here's what you put in routes.py:

routers = dict(
BASE = dict( default_application='myapp' ),
)

That's it. And it's smart enough to know how to do the right thing with URLs like:

http://domain.com/myapp/default/myapp
or http://domain.com/myapp/myapp/index

...where normal shortening would be ambiguous.


If you have two applications, myapp and myapp2, you'll get the same effect, and additionally myapp2's default controller will be stripped from the URL whenever it's safe (which is mostly all the time).

Another case. Suppose you want to support URL-based languages, where your URLs look like this:

http://myapp/en/some/path

or (rewritten)

http://en/some/path

Here's how:

routers = dict(
BASE = dict( default_application='myapp' ),
myapp = dict( languages=['en', 'it', 'jp'], default_language='en' ),
)

Now an incoming URL like this:

http:/domain.com/it/some/path

will be routed to /myapp/some/path, and request.uri_language will be set to 'it', so you can force the translation. You can also have language-specific static files.

http://domain.com/it/static/filename

will be mapped to:

applications/myapp/static/it/filename

...if that file exists. If it doesn't, then URLs like:

http://domain.com/it/static/base.css

...will still map to:

applications/myapp/static/base.css

(because there is no static/it/base.css)

So you can now have language-specific static files, including images, if you need to.


Domain mapping is supported as well.

routers = dict(
BASE = dict(
domains = {
'domain1.com' : 'app1',
'domain2.com' : 'app2',
}
),
)

does what you'd expect.

routers = dict(
BASE = dict(
domains = {
'domain.com:80' : 'app/insecure',
'domain.com:443' : 'app/secure',
}
),
)

...maps http://domain.com accesses to app's controller named 'insecure', while https accesses go to the 'secure' controller. Or you can map different ports to different apps, in the obvious way.


There's more, but mostly everything happens automatically, and there's no need to dig into the details of configuration unless there's some non-standard thing you need. There's a bit more documentation in router.example.py.

cjrh

unread,
Feb 17, 2011, 12:49:00 AM2/17/11
to web2py-users
On Feb 16, 11:38 pm, Jonathan Lundell <jlund...@pobox.com> wrote:
> [I'm reposting this message from a while back, because the new release 1.92.1 contains it for the first time. It describes some simple use cases for the new URL router. Note that there are still some things that you'll need the existing regex-based router for, but for most cases the new one should work and be easier to configure.]

May I add this text to the book, now that the router is in the latest
stable release version? I don't want to step on your toes, if you
were planning to do this yourself soon anyway, then that's fine too.

regards
cjrh

Jonathan Lundell

unread,
Feb 17, 2011, 1:02:57 AM2/17/11
to web...@googlegroups.com

Please do. Take a look at router.example.py as well; there's at least one new feature there (path_prefix). I can review the material any time you're ready.


cjrh

unread,
Feb 17, 2011, 1:26:48 AM2/17/11
to web2py-users
Ok, I'll give it a shot. I read through (skimmed, tbh)
router.example.py last night, it's quite comprehensive. For the book,
I would prefer to put a whole bunch of examples of typical use cases
in addition to the formal feature spec since many people, me included,
grok examples much faster than specs.

Johann Spies

unread,
Feb 17, 2011, 7:58:34 AM2/17/11
to web...@googlegroups.com
I am afraid router.example.py did not help me a lot.

What is unclear to me is how to use root_static.  The documetation says:

#  root_static: list of static files accessed from root
#       (mapped to the current application's static/ directory)
#       Each application has its own root-static files.

The example did not show any reference to an application.

So do I have to list all the  files all the applications will user from 'static' in the same list?

I have two applications and at the moment have the following:

   # base router                                                                                                            
    BASE = dict(                                                                                                             
        default_application = 'kb',                                                                                          
        domains = {                                                                                                          
                 'kbase.sun.ac.za' : 'kb',                                                                                   
                'kbase' : 'kb',                                                                                              
                'sadcpublications.sun.ac.za' : 'sadec'                                                                       
                },                                                                                                           
        applications = ['kb', 'sadec'],
        controllers = 'DEFAULT'                                                                                              
    ),                                      

Both sadec and  kb makes use of a front page image:
in sadec/static for sadec
and in
kb/static/images for kb

While sadec shows the image kb can't find it.

I have used autoroutes before but that breaks jqgrid.  Now with this jqgrid seems to work.

If I can just solve the problem of <app>/static/images it will help - that is until I discover something else routes.py has broken...

Regards
Johann

--
 May grace and peace be yours in abundance through the full knowledge of God and of Jesus our Lord!  His divine power has given us everything we need for life and godliness through the full knowledge of the one who called us by his own glory and excellence.
                                                    2 Pet. 1:2b,3a

Jonathan Lundell

unread,
Feb 17, 2011, 10:52:24 AM2/17/11
to web...@googlegroups.com
On Feb 17, 2011, at 4:58 AM, Johann Spies wrote:
On 17 February 2011 08:02, Jonathan Lundell <jlun...@pobox.com> wrote:
On Feb 16, 2011, at 9:49 PM, cjrh wrote:
>
> On Feb 16, 11:38 pm, Jonathan Lundell <jlund...@pobox.com> wrote:
>> [I'm reposting this message from a while back, because the new release 1.92.1 contains it for the first time. It describes some simple use cases for the new URL router. Note that there are still some things that you'll need the existing regex-based router for, but for most cases the new one should work and be easier to configure.]
>
> May I add this text to the book, now that the router is in the latest
> stable release version?    I don't want to step on your toes, if you
> were planning to do this yourself soon anyway, then that's fine too.

Please do. Take a look at router.example.py as well; there's at least one new feature there (path_prefix). I can review the material any time you're ready.


I am afraid router.example.py did not help me a lot.

What is unclear to me is how to use root_static.  The documetation says:

#  root_static: list of static files accessed from root
#       (mapped to the current application's static/ directory)
#       Each application has its own root-static files.

The example did not show any reference to an application.

So do I have to list all the  files all the applications will user from 'static' in the same list?

No, this is a special case for favicon.ico and robots.txt

By "root_static" (which I agree is a little confusing), we mean static files like favicon.ico that are always accessed in the server root. This is simply a list of those files (and the default list should normally be all you need) that tells web2py which application's static directory to fetch the files from.


I have two applications and at the moment have the following:

   # base router                                                                                                             
    BASE = dict(                                                                                                              
        default_application = 'kb',                                                                                           
        domains = {                                                                                                           
                 'kbase.sun.ac.za' : 'kb',                                                                                    
                'kbase' : 'kb',                                                                                               
                'sadcpublications.sun.ac.za' : 'sadec'                                                                        
                },                                                                                                            
        applications = ['kb', 'sadec'],
        controllers = 'DEFAULT'                                                                                               
    ),                                       

Both sadec and  kb makes use of a front page image:
in sadec/static for sadec
and in
kb/static/images for kb

While sadec shows the image kb can't find it.

I have used autoroutes before but that breaks jqgrid.  Now with this jqgrid seems to work. 

If I can just solve the problem of <app>/static/images it will help - that is until I discover something else routes.py has broken... 

What are the actual URLs for the images in question? As they appear in the page source at the browser, I mean.

Johann Spies

unread,
Feb 17, 2011, 1:37:10 PM2/17/11
to web...@googlegroups.com

No, this is a special case for favicon.ico and robots.txt

By "root_static" (which I agree is a little confusing), we mean static files like favicon.ico that are always accessed in the server root. This is simply a list of those files (and the default list should normally be all you need) that tells web2py which application's static directory to fetch the files from.


I have two applications and at the moment have the following:

   # base router                                                                                                             
    BASE = dict(                                                                                                              
        default_application = 'kb',                                                                                           
        domains = {                                                                                                           
                 'kbase.sun.ac.za' : 'kb',                                                                                    
                'kbase' : 'kb',                                                                                               
                'sadcpublications.sun.ac.za' : 'sadec'                                                                        
                },                                                                                                            
        applications = ['kb', 'sadec'],
        controllers = 'DEFAULT'                                                                                               
    ),                                       

Both sadec and  kb makes use of a front page image:
in sadec/static for sadec
and in
kb/static/images for kb

While sadec shows the image kb can't find it.

I have used autoroutes before but that breaks jqgrid.  Now with this jqgrid seems to work. 

If I can just solve the problem of <app>/static/images it will help - that is until I discover something else routes.py has broken... 

What are the actual URLs for the images in question? As they appear in the page source at the browser, I mean.


src="/kb/static/DSC_1403.png" (I moved the image from /kb/static/images to /kb/static - now it works. 
I would still like to know how to get imgages in static/images to work with this routing system.

src="/sadec/static/sadc.png" 

Regards
Johann

Jonathan Lundell

unread,
Feb 17, 2011, 2:33:59 PM2/17/11
to web...@googlegroups.com
On Feb 17, 2011, at 10:37 AM, Johann Spies wrote:
> What are the actual URLs for the images in question? As they appear in the page source at the browser, I mean.
>
>
> src="/kb/static/DSC_1403.png" (I moved the image from /kb/static/images to /kb/static - now it works.
>
> I would still like to know how to get imgages in static/images to work with this routing system.
>
>
> src="/sadec/static/sadc.png"

It should "just work". Can you double-check your names?

Also, please try it (with files in static/images) with routing turned off (rename routes.py and restart web2py).

If that doesn't resolve things, I'll try a more extended test at my end.

I wrote a unit test, below, that seems to work OK. The extra kb & sadec router entries are there because the apps aren't in my file system; you don't need them.

def test_johann_spies(self):
'''
test Johann Spies router
'''
router_js = dict(


BASE = dict(
default_application = 'kb',
domains = {
'kbase.sun.ac.za' : 'kb',
'kbase' : 'kb',
'sadcpublications.sun.ac.za' : 'sadec'
},
applications = ['kb', 'sadec'],

),
kb = dict(),
sadec = dict(),
)
load(rdict=router_js)
self.assertEqual(filter_url('http://kbase.sun.ac.za/'),
'/kb/default/index')
self.assertEqual(filter_url('http://kbase/'),
'/kb/default/index')
self.assertEqual(filter_url('http://sadcpublications.sun.ac.za/'),
'/sadec/default/index')
self.assertEqual(filter_url('http://kbase.sun.ac.za/static/file.css'),
'%s/applications/kb/static/file.css' % root)
self.assertEqual(filter_url('http://kbase.sun.ac.za/static/file.css'),
'%s/applications/kb/static/file.css' % root)
self.assertEqual(filter_url('http://kbase.sun.ac.za/static/DSC_1403.png'),
'%s/applications/kb/static/DSC_1403.png' % root)
self.assertEqual(filter_url('http://kbase.sun.ac.za/static/images/DSC_1403.png'),
'%s/applications/kb/static/images/DSC_1403.png' % root)
self.assertEqual(filter_url('http://kbase/static/images/DSC_1403.png'),
'%s/applications/kb/static/images/DSC_1403.png' % root)

pbreit

unread,
Feb 17, 2011, 2:54:23 PM2/17/11
to web...@googlegroups.com
I'm still confused by routing.

1) I see routers.example.py and routes.example.py. Which do I use? Should it be named routers.py or routes.py? Do they work together? Which can be used at the app level?

2) What would a routing file look like that matches the current default routing behavior? I would much prefer to have explicit routing. I don't like that routing is "off" be default.

3) I would think one of the most important and simplest use cases would be: hide the default application name, hide "default" and hide "index". This would be so that someone could role out one application on a server and have clean, user-friendly URLs.

4) Does the new routing functionality support mixed regex and non-regex?

Jonathan Lundell

unread,
Feb 17, 2011, 5:08:45 PM2/17/11
to web...@googlegroups.com
On Feb 17, 2011, at 11:54 AM, pbreit wrote:
> I'm still confused by routing.
>
> 1) I see routers.example.py and routes.example.py. Which do I use? Should it be named routers.py or routes.py? Do they work together? Which can be used at the app level?

You choose one or the other, as routes.py.

Either can be used at the app level, though if you do so, you need a root routes.py as well.

With router.example.py, it's probably just as easy to put the app-specfic routing configuration(s) in the root router, though.

> 2) What would a routing file look like that matches the current default routing behavior? I would much prefer to have explicit routing. I don't like that routing is "off" be default.

"Routing" is perhaps a slightly misleading name. The default is to treat the first three elements of a URL as application/controller/function, to split the remaining path elements into request.args (a list), and to put the query string in request.vars (a dictionary).

If there are fewer than three elements in the URL, the URL is (effectively) filled out as required with /init/default/index.

The function of routes.py is to map the incoming URL to the above format, and vice versa for outgoing URLs.

> 3) I would think one of the most important and simplest use cases would be: hide the default application name, hide "default" and hide "index". This would be so that someone could role out one application on a server and have clean, user-friendly URLs.

Yes.

> 4) Does the new routing functionality support mixed regex and non-regex?

No, though it's on the list for future enhancement.

Jonathan Lundell

unread,
Feb 18, 2011, 11:12:41 AM2/18/11
to web...@googlegroups.com
On Feb 17, 2011, at 10:37 AM, Johann Spies wrote:
src="/kb/static/DSC_1403.png" (I moved the image from /kb/static/images to /kb/static - now it works.
I would still like to know how to get imgages in static/images to work with this routing system.


I tested this with one of my apps that uses several subdirectories in static, and it seems to work fine. (This is with 1.92.1.)

Can you tell where the problem is? When you add the images directory, do the URLs in the browser look OK?

cjrh

unread,
Feb 18, 2011, 1:16:35 PM2/18/11
to web2py-users
On Feb 17, 8:02 am, Jonathan Lundell <jlund...@pobox.com> wrote:
> Please do. Take a look at router.example.py as well; there's at least one new feature there (path_prefix). I can review the material any time you're ready.

Ok, here is a first draft.

http://web2py.com/book/default/chapter/11#Modify-the-URL-with-the-Router

I followed your guide pretty faithfully, mosly adding the markmin
markup where application. Now at least you (and others) can refer
people to the formal documentation.

If you want me to add or change stuff, please email me directly.
Google groups makes it too difficult to keep track of older threads.

cjrh

unread,
Feb 18, 2011, 1:25:52 PM2/18/11
to web2py-users
On Feb 18, 8:16 pm, cjrh <caleb.hatti...@gmail.com> wrote:
> Ok, here is a first draft.
>
> http://web2py.com/book/default/chapter/11#Modify-the-URL-with-the-Router

http://web2py.com/book/default/chapter/11#Modifying-the-URL

(refactored the section heading)

Anthony

unread,
Feb 18, 2011, 2:46:35 PM2/18/11
to web...@googlegroups.com
This is great. To avoid confusion, though, would it make more sense to move this material into the "URL Rewrite" section of Chapter 4: http://web2py.com/book/default/chapter/04#URL-Rewrite
 
Maybe keep the first paragraph of that section and then mention that there are now two distinct URL rewriting systems -- for most use cases, a fairly simple router-based system (involving dictionaries of routing parameters), and for more complex cases, a powerful regular expression based system. Then create two subsections to explain the two systems (e.g., "Router System" and "Pattern Matching System", or something along those lines). For app-specific routing, we could either keep the "Application-Specific URL Rewrite" subsection (http://web2py.com/book/default/chapter/04#Application-Specific-URL-Rewrite) and simply expand it to include the new router system, or instead include separate app-specific rewrite subsections within the Router and Pattern Matching sections.
 
It's also probably worth mentioning the following somewhere:
  • Although the router example file is called router.example.py, the routers still need to go in routes.py (i.e., not router.py).
  • You cannot mix router dictionaries with the old regex routes_in and routes_out (yet).
  • routes_onerror still works the same regardless of which routing system you're using (i.e., still regex based).
Anthony

On Friday, February 18, 2011 1:16:35 PM UTC-5, cjrh wrote:

pbreit

unread,
Feb 18, 2011, 3:57:54 PM2/18/11
to web...@googlegroups.com
How do I hide "/myapp/default" ?

Jonathan Lundell

unread,
Feb 18, 2011, 4:03:48 PM2/18/11
to web...@googlegroups.com
On Feb 18, 2011, at 12:57 PM, pbreit wrote:
> How do I hide "/myapp/default" ?

Just set default_application (in BASE) to "myapp". default_controller is set to "default" by default, and the rest happens automatically.


I made a change just before the 1.92.1 release. By default, static URLs are not shortened. In this case, URLs like /myapp/static/something don't have "myapp" hidden.

There are two reasons for this. One is that static URLs are typically invisible to users, so it doesn't matter. The more important reason is to make life easier for external routing of static URLs (by Apache or GAE, for example).

You can override this behavior, and get app-hiding back for static URLs, by setting map_static=True.

pbreit

unread,
Feb 18, 2011, 4:32:56 PM2/18/11
to web...@googlegroups.com
Ah, ok. Yeah it's working correctly.

Johann Spies

unread,
Feb 23, 2011, 2:47:51 AM2/23/11
to web...@googlegroups.com
On 17 February 2011 21:33, Jonathan Lundell <jlun...@pobox.com> wrote:
On Feb 17, 2011, at 10:37 AM, Johann Spies wrote:
> What are the actual URLs for the images in question? As they appear in the page source at the browser, I mean.
>
>
> src="/kb/static/DSC_1403.png" (I moved the image from /kb/static/images to /kb/static - now it works.
>
>  I would still like to know how to get imgages in static/images to work with this routing system.
>
>
> src="/sadec/static/sadc.png"

It should "just work". Can you double-check your names?

Also, please try it (with files in static/images) with routing turned off (rename routes.py and restart web2py).

If that doesn't resolve things, I'll try a more extended test at my end.

Without the routes.py file I can work with the image in static/images but not when routes.py is active.

Regards
Johann
 
--

Jonathan Lundell

unread,
Feb 23, 2011, 3:04:42 AM2/23/11
to web...@googlegroups.com
On Feb 22, 2011, at 11:47 PM, Johann Spies wrote:
> On 17 February 2011 21:33, Jonathan Lundell <jlun...@pobox.com> wrote:
> On Feb 17, 2011, at 10:37 AM, Johann Spies wrote:
> > What are the actual URLs for the images in question? As they appear in the page source at the browser, I mean.
> >
> >
> > src="/kb/static/DSC_1403.png" (I moved the image from /kb/static/images to /kb/static - now it works.
> >
> > I would still like to know how to get imgages in static/images to work with this routing system.
> >
> >
> > src="/sadec/static/sadc.png"
>
> It should "just work". Can you double-check your names?
>
> Also, please try it (with files in static/images) with routing turned off (rename routes.py and restart web2py).
>
> If that doesn't resolve things, I'll try a more extended test at my end.
>
> Without the routes.py file I can work with the image in static/images but not when routes.py is active.

With routes.py in place, can you access something in static/images with their full (unshortened) URL?

And is this still the routers dict you're using? Anything besides BASE?

# base router

BASE = dict(
default_application = 'kb',
domains = {
'kbase.sun.ac.za' : 'kb',
'kbase' : 'kb',
'sadcpublications.sun.ac.za' : 'sadec'
},
applications = ['kb', 'sadec'],

controllers = 'DEFAULT'
),

Jonathan Lundell

unread,
Mar 1, 2011, 6:42:38 PM3/1/11
to web...@googlegroups.com
On Feb 17, 2011, at 10:37 AM, Johann Spies wrote:
src="/kb/static/DSC_1403.png" (I moved the image from /kb/static/images to /kb/static - now it works. 
I would still like to know how to get imgages in static/images to work with this routing system.

src="/sadec/static/sadc.png" 

Have you made any progress with this? I still haven't been able to reproduce the problem, using the standard web2py apps, all of which have several static subdirectories.

Jonathan Lundell

unread,
Mar 2, 2011, 2:41:39 AM3/2/11
to web...@googlegroups.com
On Feb 22, 2011, at 11:47 PM, Johann Spies wrote:
> Without the routes.py file I can work with the image in static/images but not when routes.py is active.

Is it possible that you were using URL calls like this:

URL(... c='static/images', f='filename') ?

If so, try changing them to this:

URL(... c='static', f='images/filename')

Massimo Di Pierro

unread,
Mar 2, 2011, 9:12:47 AM3/2/11
to web2py-users
or simply

URL('static','images/filename')

the f= and c= are no longer necessary.

Johann Spies

unread,
Mar 3, 2011, 1:24:11 AM3/3/11
to web...@googlegroups.com
Hallo Jonathan,


No.  It is a production server so I do not want to experiment a lot.  When I remove routes.py the server serves the pictures in the subdirectory /static/images/  but when I use routes.py the images have to be in /static.  So I just moved them to static.

Here is my routes.py (the routers part)

routers = dict(

    # base router
    BASE = dict(
        default_application = 'kb',
        domains = {
                 'kbase.sun.ac.za' : 'kb',
                'kbase' : 'kb',
                'sadcpublications.sun.ac.za' : 'sadec'
                },
        applications = ['kb', 'sadec', 'ada', 'admin'],
        controllers = 'DEFAULT'
    ),
    # 'admin' application router
    admin = dict(
        controllers = [],   # don't remove controller names from admin URLs
        map_hyphen = False, # don't map hyphens to underscores
    ),
)
 

Jonathan Lundell

unread,
Mar 3, 2011, 1:39:58 AM3/3/11
to web...@googlegroups.com
On Mar 2, 2011, at 10:24 PM, Johann Spies wrote:
> No. It is a production server so I do not want to experiment a lot. When I remove routes.py the server serves the pictures in the subdirectory /static/images/ but when I use routes.py the images have to be in /static. So I just moved them to static.

Do you have any URL calls with 'static/images' in them? (That is, in the non-working case.) Under some circumstances they won't work, in particular when there's a hyphen or underscore in the filename.

The fix (until the next version, anyway) is to change calls like URL('static/image', 'file') to URL('static', 'image/file'). The reason is that 'static' is treated as the name of the controller directory, and 'static/image' isn't recognized in the current version.

Johann Spies

unread,
Mar 3, 2011, 2:10:03 AM3/3/11
to web...@googlegroups.com
On 3 March 2011 08:39, Jonathan Lundell <jlun...@pobox.com> wrote:

The fix (until the next version, anyway) is to change calls like URL('static/image', 'file') to URL('static', 'image/file'). The reason is that 'static' is treated as the name of the controller directory, and 'static/image' isn't recognized in the current version.

Thanks.  This fix worked for me.

Jonathan Lundell

unread,
Mar 3, 2011, 2:14:00 AM3/3/11
to web...@googlegroups.com
On Mar 2, 2011, at 11:10 PM, Johann Spies wrote:
On 3 March 2011 08:39, Jonathan Lundell <jlun...@pobox.com> wrote:

The fix (until the next version, anyway) is to change calls like URL('static/image', 'file') to URL('static', 'image/file'). The reason is that 'static' is treated as the name of the controller directory, and 'static/image' isn't recognized in the current version.

Thanks.  This fix worked for me.

Glad to hear it. This one was driving me nuts.

Tom Atkins

unread,
Mar 21, 2011, 5:37:42 PM3/21/11
to web...@googlegroups.com
I am designing an app with a URL structure like this:


'yoursitename' is effectively an argument as there could be many sites and users are allowed to create their own sites. But I'd like it to be 'top level'.

Then within yoursitename there will be URLs like this:


I have a black-list of reserved top level words (e.g. /admin /about /faq /account etc) that are not allowed to be chosen.  So the site will have controllers to expose pages like:


My question is what's the best / most efficient way to serve /yoursitename and the associated controllers?

(I hope that makes sense!)

VP

unread,
Mar 21, 2011, 5:51:55 PM3/21/11
to web2py-users
I think each "yoursitename" should be a different app. I think it's
most efficient that way.

Tom Atkins

unread,
Mar 21, 2011, 5:55:47 PM3/21/11
to web...@googlegroups.com
Just to  clarify - each 'yoursitename' is part of the same app - it could be 'youusername' or 'yourorganisation' depending on the app.  e.g. see github's url structure:


isotoma is the 'username' or 'yoursitename' - it's top level but user chosen.  They also have reserved URLs like:

David Warnock

unread,
Mar 21, 2011, 6:08:01 PM3/21/11
to web...@googlegroups.com
Tom,

I am designing an app with a URL structure like this:


'yoursitename' is effectively an argument as there could be many sites and users are allowed to create their own sites. But I'd like it to be 'top level'.

An alternative might be to use subdomains eg


I am looking at this for deployment on google app engine (and have not yet looked at web2py support for it). My understanding is that google app engine can automatically use the subdomain to restrict the view of the data so that if I am logged into a.myapp,com I won't be able to access the data for b.myapp.com

Sub domains give you nice scaling options in the future such as separate servers for each domain.

What I can't help you with (because I am a web2py newbie) is how to make this work within web2py.

Hope this helps

Dave
 
--
Dave Warnock: http://42.blogs.warnock.me.uk

Tom Atkins

unread,
Mar 21, 2011, 6:12:04 PM3/21/11
to web...@googlegroups.com
Thanks for the reply - I've considered the subdomain option but don't want to use it in this case.  This article:


was previously linked on the forum and summarises very well the reasons I'm keen to go for a URL structure as proposed.

On 21 March 2011 22:08, David Warnock <da...@warnock.me.uk> wrote:
Tom,

Jonathan Lundell

unread,
Mar 21, 2011, 6:30:23 PM3/21/11
to web...@googlegroups.com

What would be the mapping of, say, myapp.com/yoursitename/xyz? As a fully-expanded web2py URL? What are the app/controller/functions?

If I understand your requirement correctly, the new router logic will do what you want. You'll need to specify a functions list in order to enable removal of the default function from the URL. So the expanded URL would be:

myapp.com/yoursitename/users -> myapp.com/app/default/index/yoursitename/users, so you'd have request.args=['yoursitename', 'users'], and your default function would decide what to do with it.

/admin and the like could be functions (like /app/default/admin), in which case you'd want to say: functions=['admin', 'about', 'faq', 'accounts', 'etc'] in the router control dict, or they can be controllers.

Tom Atkins

unread,
Mar 21, 2011, 7:05:31 PM3/21/11
to web...@googlegroups.com
Thanks Jonathan!

What would be the mapping of, say, myapp.com/yoursitename/xyz?

yoursitename would be the first arg
I guess xyz would be the second arg - although it'd be handy if it could be a controller or function!

Your suggestion solves my problem - I've just added:

functions=['admin', 'about', 'faq', 'accounts', 'etc']

to the dict for the app in routes.py and everything works (so far)!

As you suggest my index function in the default controller now handles the args for /yoursitename etc just fine.

So all I need to do now is add all black-listed functions to that list of values as I go along.... functional but not very elegant. 

I was playing with Flask and I have to say its solution to routing is very nice:


The use of variable names anywhere within the URL structure is very handy. Anything like this possible in web2py?

pbreit

unread,
Mar 21, 2011, 7:49:16 PM3/21/11
to web...@googlegroups.com, Jonathan Lundell
Yeah, I suspect it can be done with routing. This might be a common use case (ex: Github, Bitbucket, Twitter) so wondering if it's worth making sure it's well-supported?

Indra Gunawan

unread,
Mar 21, 2011, 10:44:32 PM3/21/11
to web...@googlegroups.com
Agree, Flask way looks more elegant (see Variable Rules). It could be nice if this way also exists on Web2Py.  


On 22 March 2011 06:05, Tom Atkins <mink...@gmail.com> wrote:
I was playing with Flask and I have to say its solution to routing is very nice:


The use of variable names anywhere within the URL structure is very handy. Anything like this possible in web2py?
 
--
coderbuzz

Jonathan Lundell

unread,
Mar 22, 2011, 1:23:57 AM3/22/11
to web...@googlegroups.com
Flask doesn't really allow variable names anywhere; near as I can tell they're a considerably restricted version of web2py's args list.

Tom Atkins

unread,
Mar 22, 2011, 4:13:02 AM3/22/11
to web...@googlegroups.com
I might be being naive here but in Flask I can do:

@app.route('/<yoursitename>/users')
... def editusers(yoursitename): pass

print url_for('editprofile', yoursitename='Supersite')

gives:

/Supersite/users

Tom Atkins

unread,
Mar 22, 2011, 4:14:12 AM3/22/11
to web...@googlegroups.com
sorry - should have been:

@app.route('/<yoursitename>/users')
... def editusers(yoursitename): pass

print url_for('editusers', yoursitename='Supersite')

gives:

/Supersite/users

Jonathan Lundell

unread,
Mar 22, 2011, 10:49:55 AM3/22/11
to web...@googlegroups.com
On Mar 22, 2011, at 1:14 AM, Tom Atkins wrote:

sorry - should have been:

@app.route('/<yoursitename>/users')
... def editusers(yoursitename): pass

print url_for('editusers', yoursitename='Supersite')

gives:

/Supersite/users

Maybe so. Is there a formal definition of how Flask's routing works? All I could find was a rather brief overview at the quickstart link.

Tom Atkins

unread,
Mar 22, 2011, 12:06:05 PM3/22/11
to web...@googlegroups.com
It uses Werkzeug - full details here:

pbreit

unread,
Mar 22, 2011, 2:12:50 PM3/22/11
to web...@googlegroups.com, Jonathan Lundell
Would there be any way to support something like:

/$user/app/controller/function

Where $user is available to controllers as some sort of arg?

I could see your idea about re-formatting the URL to: /app/controller/function/$user but am wondering if that will be hard to manage?

David J.

unread,
Mar 22, 2011, 2:31:14 PM3/22/11
to web...@googlegroups.com
The former is semantically more correct;

$user/app/controller/etc...

It seems the domain is obviously the root of any app; then the "user"
selected name should be the next logical level; then any functions that
user has access to should be listed;

Jonathan Lundell

unread,
Mar 22, 2011, 2:37:20 PM3/22/11
to web...@googlegroups.com

I think that the only way to do it right now is by using the regex router to rewrite the URL, as above ($user should end up in request.args). I don't think it'd be all that hard to manage. You'd want to establish some rule for recognizing the case where the first element isn't a $user (say on initial login).

Indra Gunawan

unread,
Mar 23, 2011, 12:21:37 AM3/23/11
to web...@googlegroups.com
Warning, TMIIW; Those technique require to load all exposed functions, 
it won't act as lazy load (load on demand).

Thats I've read on Flask book :)

On 22 March 2011 23:06, Tom Atkins <mink...@gmail.com> wrote:

--
coderbuzz

Massimo Di Pierro

unread,
Mar 23, 2011, 9:17:31 AM3/23/11
to web2py-users
This is not an option in web2py because the controller is executed
after the requests arrives not imported before (as in Flask). Anyway,
that works better for simple apps but becomes a mess if you have many
functions because the routing info is scattered all over the place.
Moreover - when it comes to rest - it requires that you use the same
function for multiple methods (GET/POST/etc) by using multiple
decorators or that you use different functions with different names to
handle different names (I do not like that).

On Mar 22, 3:13 am, Tom Atkins <minkto...@gmail.com> wrote:
> I might be being naive here but in Flask I can do:
>
> @app.route('/<yoursitename>/users')
> ... def editusers(yoursitename): pass
>
> print url_for('editprofile', yoursitename='Supersite')
>
> gives:
>
> /Supersite/users
>
> On 22 March 2011 05:23, Jonathan Lundell <jlund...@pobox.com> wrote:
>
>
>
>
>
>
>
> > On Mar 21, 2011, at 7:44 PM, Indra Gunawan wrote:
>
> > Agree, Flask way looks more elegant (see Variable Rules). It could be nice
> > if this way also exists on Web2Py.
>

Anthony

unread,
Mar 23, 2011, 9:31:56 AM3/23/11
to web...@googlegroups.com, Massimo Di Pierro
Massimo, I think Tom was referring to Flask's ability to include an arg at an arbitrary place in the URL path (e.g., '/<yoursitename>/users'), not the ability to specify the routes via decorators. I think the former *can* be achieved in web2py using the pattern-based rewrite system, right?
 
Anthony

On Wednesday, March 23, 2011 9:17:31 AM UTC-4, Massimo Di Pierro wrote:
This is not an option in web2py because the controller is executed
after the requests arrives not imported before (as in Flask). Anyway,
that works better for simple apps but becomes a mess if you have many
functions because the routing info is scattered all over the place.
Moreover - when it comes to rest - it requires that you use the same
function for multiple methods (GET/POST/etc) by using multiple
decorators or that you use different functions with different names to
handle different names (I do not like that).

Massimo Di Pierro

unread,
Mar 23, 2011, 9:46:20 AM3/23/11
to web...@googlegroups.com
yes. For example:

routes_in = [
  ('/$yoursitename/users','/init/default/users/$yoursitename'),
]

the optionally

@request.restful()
def users():
      def GET(yoursitename):
             return dict(message='your site name is: '+yoursitename)
      return locals()

VP

unread,
Mar 24, 2011, 10:56:01 AM3/24/11
to web2py-users
Can't this be done in web2py with something like this?

assert(request.args(1) == 'users')
yoursitename = request.args(0)

VP

unread,
Mar 24, 2011, 11:04:39 AM3/24/11
to web2py-users
Noticing the version of web2py keeps interestingly increasing to 2.0,
I think this is something Massimo might want to spend sometime
thinking about.

As I understand it, because of "exec", controllers are called *after*
the request arrives. This allows web2py to do a few interesting
things that other frameworks can't.

On the other hands, this is an example that shows an advantage of
being able to manipulate controllers (concisely) *before* the request
arrives.

I found myself constantly type checking controller arguments (e.g.
making sure an "id" is a number). This is another example where being
able to specify a certain syntax to the URL is very helpful.

Jonathan Lundell

unread,
Mar 24, 2011, 11:26:51 AM3/24/11
to web...@googlegroups.com

Notice that the routing mechanism you're talking about doesn't depend on the routing information being distributed as controller decoration; they can be presented in a table instead. In fact, putting them in a table has advantages over the decorator approach, in that a) you can see the whole routing policy in one place, and b) you can explicitly specify the order of evaluation.

Checking controller arguments is important, since they are, after all, user input and not trustworthy. And there's something to be said for checking them at the controller/function, since you're in a position to give more informative error messages if something is wrong.

If you're using web2py forms, then the validators serve this purpose. If you're not, you can use the validators on their own.

Anthony

unread,
Mar 24, 2011, 11:32:54 AM3/24/11
to web...@googlegroups.com, VP
On Thursday, March 24, 2011 11:04:39 AM UTC-4, VP wrote:
Noticing the version of web2py keeps interestingly increasing to 2.0,
I think this is something Massimo might want to spend sometime
thinking about.
 
I don't think the xx part of 1.xx.y is to be interpreted as a decimal with a maximum of 99 -- I think it's just the number of releases within the 1.0 series (so, can go over 99).

Martín Mulone

unread,
Mar 24, 2011, 11:49:58 AM3/24/11
to web...@googlegroups.com
I really want to see routes in the application folder. Routes in the past was hard to follow, now I think the work of Johnatan make it more easy. But when you have many applications, the routes for all is a bit messy. I don't know if this can be done:

For example a simple case:

Main routes.py:
---------------

Domain Application
---------------------------------



Aplication:  applications/domain1/routes.py:
-------------------------------------------


[routes In]
In Out
----------------------------------
/favicon.ico /static/favicon.ico


[routes Out]
In Out
----------------------------------
default/index /
plugin_i2p/view/333 /view/333


2011/3/24 VP <vtp...@gmail.com>



--
My blog: http://martin.tecnodoc.com.ar
Expert4Solution Profile: http://www.experts4solutions.com/e4s/default/expert/6


Anthony

unread,
Mar 24, 2011, 12:06:23 PM3/24/11
to web...@googlegroups.com, mar...@tecnodoc.com.ar
I believe this is already possible, no?
 
The book describes app-specific routing for the old system: http://web2py.com/book/default/chapter/04#Pattern-Based-System
 
And  for the new system, the router.example.py file (http://code.google.com/p/web2py/source/browse/router.example.py) mentions you can have an app-specific router in applications/app/routes.py.
 
Anthony

Martín Mulone

unread,
Mar 24, 2011, 12:51:56 PM3/24/11
to web...@googlegroups.com
Yes but not in the application folder. The importance is to be distributed with the application.

2011/3/24 Anthony <abas...@gmail.com>

Tom Atkins

unread,
Mar 24, 2011, 12:50:02 PM3/24/11
to web...@googlegroups.com
The problem for me is not being able to mix the new parameter-based routing with the pattern-based system (my regex skills are not good enough to make the patten system do what I want....) .  

Is it possible to have parameter system in the global routes.py and then pattern system in the app-specific routes.py?  That would solve my issues!

Martín Mulone

unread,
Mar 24, 2011, 12:57:06 PM3/24/11
to web...@googlegroups.com
For example I have a blog application with this url


I can short to this:


with this one route:

(r'.*:/blog/(?P(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01]).*)$',r'/blog/default/post/\g')

Not easy to read :) if I can make it transparent to the user that the user not have to worried about routes. 

2011/3/24 Martín Mulone <mulone...@gmail.com>

Jonathan Lundell

unread,
Mar 24, 2011, 1:23:48 PM3/24/11
to web...@googlegroups.com
On Mar 24, 2011, at 9:57 AM, Martín Mulone wrote:
> For example I have a blog application with this url
>
> http://www.mysite.com/blog/default/post/2010/10/10/my-article
>
> I can short to this:
>
> http://www.mysite.com/blog/2010/10/10/my-article
>
> with this one route:
>
> (r'.*:/blog/(?P(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01]).*)$',r'/blog/default/post/\g')
>
> Not easy to read :) if I can make it transparent to the user that the user not have to worried about routes.

You can do this with the new router if you make post the default function of the blog app, and create a list of functions in blog/default. Something like this:

routers = dict(

blog = dict(
default_function='post',
functions=['index', 'user', 'post', 'whatever'],
),
)

You'll need to parse and validate the args in default/post.

By specifying a list of functions in the default controller, you're telling the router that it can unambiguously omit the 'post' name if there's no conflict. So with the router above, a URL like /blog/default/post/index would *not* be shortened to /blog/index, because that would conflict with the function named 'index'.

Anthony

unread,
Mar 24, 2011, 1:35:42 PM3/24/11
to web...@googlegroups.com, mar...@tecnodoc.com.ar
On Thursday, March 24, 2011 12:51:56 PM UTC-4, Martin.Mulone wrote:
Yes but not in the application folder. The importance is to be distributed with the application.
 
With both systesms, you can put a routes.py file in the application folder, but at least with the older system, for that to work, you also need a routes_app entry in the main routes.py file -- is that what you're saying you don't want? In other words, you want no dependency on any central routes.py file? Perhaps Jonathan can verify, but I think that may be possible with the new system (i.e., having a routes.py file in your app folder without having a routes.py file in the web2py root folder).
 
Anthony

Jonathan Lundell

unread,
Mar 24, 2011, 1:46:22 PM3/24/11
to web...@googlegroups.com
On Mar 24, 2011, at 10:35 AM, Anthony wrote:
> On Thursday, March 24, 2011 12:51:56 PM UTC-4, Martin.Mulone wrote:
> Yes but not in the application folder. The importance is to be distributed with the application.

I think you two might be talking at cross purposes here. It goes in applications/myapp/

>
> With both systesms, you can put a routes.py file in the application folder, but at least with the older system, for that to work, you also need a routes_app entry in the main routes.py file -- is that what you're saying you don't want? In other words, you want no dependency on any central routes.py file? Perhaps Jonathan can verify, but I think that may be possible with the new system (i.e., having a routes.py file in your app folder without having a routes.py file in the web2py root folder).
>

Both versions of routing work the same way, in principle. You need a base (root) routes.py so that the router can figure out the application (otherwise it wouldn't know which app-specific routes.py to use). The rest of the routing information can be in each applications root folder.

The new router's syntax makes it pretty easy to have all the routing in the base routes.py, though, since each app can simply have its own routing dict.

Tom Atkins

unread,
Mar 24, 2011, 1:59:33 PM3/24/11
to web...@googlegroups.com
Thanks for this suggestion Massimo - it's the closest to what I'm looking for.  I've tried to get it to work but no joy.

I've changed my global routes.py to use parameter based routing sand put the first part of your code in the application specific routes.py.

I've then put the 2nd part of your code into the default controller.  But if you go to:


I get:

invalid controller (Supersite/users)

I've tried but can't figure out a solution...

Anthony

unread,
Mar 24, 2011, 2:02:49 PM3/24/11
to web...@googlegroups.com, Tom Atkins
Tom, you cannot mix usage of the parameter-based and pattern-based routing systems, even if one is in the global routes.py and one is in an app-specific routes.py. You have to pick one system or the other, for now anyway.
 
Anthony

Tom Atkins

unread,
Mar 24, 2011, 2:13:17 PM3/24/11
to web...@googlegroups.com
Thanks Anthony - you're right and I do know this - just wrote the wrong thing in my previous post - I meant to say 'change to pattern-based'... make me wonder what other stupid mistakes I'm making... but double checked and I think I have everything correct and as suggested by Massimo.

pbreit

unread,
Mar 24, 2011, 6:22:38 PM3/24/11
to web...@googlegroups.com, mar...@tecnodoc.com.ar
+1 for a move towards routes default "on" and primarily controlled at the app level. But I do recognize there is an issue about what file should come in the main distribution and how to avoid it being overwritten with updates.

The default files could duplicate the current default functionality for explicitness.

Martín Mulone

unread,
Mar 24, 2011, 7:44:59 PM3/24/11
to web...@googlegroups.com
Sorry perhaps I don't express myself correctly, I'm not saying this is a bug or I can't do with the current way. I'm only saying that I think better if there are something like that in app level. It's an idea. Main routes.py to control things up to the application, and the rest by the application.

Main: routes.py:

Domain         Application
---------------------------------------------------

Aplication:  applications/domain1/routes/routes.py:

In        Out
----------------------------------
/favicon.ico /static/favicon.ico


Final result: routes.py + application/routes.

/domain1/static/favicon.ico    www.domain1.com/favicon.ico


In my experience in production I never share things between application or statics. I Think in the 97% or more of the application developed, to be in production are completely independant from the others app.




2011/3/24 pbreit <pbreit...@gmail.com>

+1 for a move towards routes default "on" and primarily controlled at the app level. But I do recognize there is an issue about what file should come in the main distribution and how to avoid it being overwritten with updates.

The default files could duplicate the current default functionality for explicitness.

pbreit

unread,
Mar 24, 2011, 9:01:28 PM3/24/11
to web...@googlegroups.com, mar...@tecnodoc.com.ar
I think I'm in agreement. App-specific routing should be controlled at the app level. I was just saying that it might be tricky to figure out how to set up the default file structure and routes to both work and handle future updates.
Reply all
Reply to author
Forward
0 new messages