Search code examples
pythonpyramidwsgipaster

Composite app route issue


In my Pyramid application, I set up a composite application with my main app on / and my admin portal on /admin.

[composite:main]
use = egg:paste#urlmap
/ = mainapp
/admin = adminapp

[app:mainapp]
use = egg:myApp#main

[app:adminapp]
use = egg:myApp#admin

I also added two separate initialization methods in my __init__.py method so that I could have two separate add_request_methods and authentication policies – one for general users and the other for admins.

To test this, I added two routes, one as:

config.add_route('admin_login_handler', '/admin/login/')

for the admin portal login, and the other as:

config.add_route('login_handler', '/login/')

for the general site login. Supposedly, I would see two different templates, one for each view, and I would have a separate request object for admins and general users – self.request.admin for admins and self.request.user for users.

However, when I go to /admin/login/, the /login/ template is shown. Basically, my main app's routes are now located under both / and /admin, and my admin routes are ignored. This is not what I wanted. But, I do get my desired self.request.admin object when viewing /admin routes, and my self.request.user object on my / routes, regardless of the template/view being shown.

How can I fix this so that routes with /admin/... are not "remapped" with my / routes, and I have two separate applications under two different routes prefixes?


Solution

  • To fix this issue, I added config.scan(ignore="myApp.views.main") to my __init__.admin_app method and, likewise, config.scan(ignore="myApp.views.admin") to my __init__.main_app method. Note the separation of the views into two files, to make this explicit and easy to deal with.

    This separated the two sets of routes between the two apps, and then I was able to have my two authorization policies take effect, along with my config.add_request_methods -- one checking the admin table and the other checking the user table -- in each of the respective initialization methods.

    config.add_request_method(AuthHelper.get_user, 'user', reify=True)  # Global user object
    

    and

    config.add_request_method(AuthHelper.get_admin, 'admin', reify=True) # Global admin object
    

    My admin routes were mapped with the implicit "route prefix" of /admin -- as per my .ini file.

    So far so good with this implementation. Hope this can help somebody at some point.