如何在不丢失管理应用程序的情况下以尽可能短的 URL 路由单个 web2py 应用程序

How to route a single web2py application with the shortest possible URL without losing the admin application

我有一个 web2py 网站,它有两个应用程序:标准管理应用程序和自定义 'myapp' 应用程序。为了便于讨论,我们假设该网站位于 'sub.projdomain.com'。几个小时以来,我一直在努力思考路线和 python 正则表达式,但我似乎无法确定我想要的功能。我正在尝试复制以下行为:

URL in address bar               Effective URL
------------------               -------------
sub.projdomain.com               sub.projdomain.com/myapp/default/index
sub.projdomain.com/              sub.projdomain.com/myapp/default/index
sub.projdomain.com/foo           sub.projdomain.com/myapp/foo/index
sub.projdomain.com/foo?p=1       sub.projdomain.com/myapp/foo/index?p=1
sub.projdomain.com/foo/?p=2      sub.projdomain.com/myapp/foo/index?p=2
sub.projdomain.com/foo/bar?p=3   sub.projdomain.com/myapp/foo/bar?p=3
sub.projdomain.com/foo/bar/?p=4  sub.projdomain.com/myapp/foo/bar?p=4
sub.projdomain.com/a             sub.projdomain.com/admin/default/site

我似乎总是遇到从页面 "sub.projdomain.com/foo/bar/" 调用 URL('login') 或 URL('/login') 并获得"sub.projdomain.com/foo/login/" 或类似形式的错误 URL。目前我正在设置 'routes_in' 和 'routes_out' 元组,因为我无法让它与 'routers' 一起工作。我觉得我忽略了应该是一组非常简单的路线。我是不是想多了?

----更新----

好吧,我想我设法找到了一组路线来获得我想要的行为,但我真的很想知道这是否是实现它的正确方法。

routes_in = (
    #Map the default index to '/'
    ('/', '/myapp/default/index'),
    #Allow the admin application to be accessed
    ('/a', '/admin/default/index'),
    ('/a/$anything', '/admin/$anything'),
    #Re-wire actions as controllers unless the controller is also specified
    ('/$controller', '/myapp/$controller/index'),
    ('/$controller/', '/myapp/$controller/index'),
    ('/$controller/$action', '/myapp/$controller/$action'),
    #Map static access to our app
    ('/static/$anything', '/myapp/static/$anything'),
)
routes_out = [(x, y) for (y, x) in routes_in]

此设置要求我仔细构造传递给 URL(..) 的参数。我希望更容易预测 URL(..) 产生的结果,但我怀疑它会比这更简单......感谢任何帮助!

您应该能够使用 parameter-based rewrite system:

获得大致相同的结果
routers = dict(
    BASE=dict(
        default_application='myapp',
        default_controller='default',
        default_function='index',
        functions=dict(
            default=['list', 'of', 'functions', 'in', 'default.py'],
            foo=['list', 'of', 'functions', 'in', 'foo.py']
        )
    ),
    admin=dict(
        default_function='site',
        functions=['list', 'of', 'functions', 'in', 'default.py']
    )
)

唯一的区别是 "admin" 应用程序在 URL 中仍然需要 "admin"(尽管我想您可以尝试通过将其文件夹重命名为"a").

注意,当 URL 附加了额外的参数(路由器需要能够区分 URL 参数和控制器功能)。

好的,我想我明白了。我还没有遇到 URL() 无法生成正确字符串的情况。我相信这可以进一步简化,但这里是:

routes_in = (
    #Map the default index to '/'
    ('/', '/myapp/default/index'),
    #Allow the admin application to be accessed
    ('/a', '/a/default/index'),
    ('/a/$anything', '/a/$anything'),
    #Re-wire actions as controllers unless the controller is also specified
    ('/$controller', '/myapp/$controller/index'),
    ('/$controller/', '/myapp/$controller/index'),
    ('/$controller/$action', '/myapp/$controller/$action'),
    #Map static access to our application
    ('/static/$anything', '/myapp/static/$anything'),
)
#Reverse only some of the mappings so that URL() works correctly
routes_out = (
    ('/myapp/default/index', '/'),
    ('/a/$anything', '/a/$anything'),
    ('/myapp/$controller/index', '/$controller'),
    ('/myapp/$controller/$action', '/$controller/$action'),
    ('/myapp/static/$anything', '/static/$anything'),
)

我将 'admin' 应用程序重命名为 'a'。每当我调用 URL() 时,我都必须显式传递 2 个参数。第一个参数始终是控制器的名称,第二个参数始终是任何 GET 请求变量后跟的操作的名称。例如。 URL('default', 'index') 用于主索引页面或 URL('foo', 'bar?param=3') 用于 foo 中的操作 bar,指定了 param。但是,URL('foo', '?indexParam=test') 是不允许的,因为在第二个参数的变量之前没有指定 index。只要我遵守这些规则,一切似乎都会始终如一。

我愿意接受任何其他建议,但这是我接受的答案。我希望这可以帮助其他人经历同样的困境。