使用自定义 directive/action 时路由匹配的控制顺序

control order that routes are matched when using a custom directive/action

在使用自定义指令创建的操作中调用 add_route 之前,我有一个 catchall 路由捕获我的请求。我怎样才能防止这种情况发生? IE。手动将 catchall 路由放在路由匹配过程的末尾,或者将我的操作 add_route 放在路由匹配过程的前面?

我尝试在 admin/routes.pyroutes.py 之间交换 includes 的顺序,但这似乎没有影响。一个快速的解决方案(现在考虑它可能是个好主意)是从 catchall 中的模式中过滤 admin。但是我觉得这会再次出现在我无法做到的地方所以我问这个问题。

__init__.py

def main(global_config, **settings):
    #...
    config.include('.directives')
    #...
    config.include(".routes")
    #...
    for k in (".customer", ".admin"):
        config.scan(k) # this picks up the admin/admin_routes.py

    return config.make_wsgi_app()   

admin/routes.py

def includeme(config):
    config.add_dispatched_route(
        "admin-plants-edit",
        "/admin/plants/{id}",
        'plant',
    )

routes.py


def includeme(config):
    #...
    config.add_route("page-view", "/*url")

directives.py


from pyramid.config import PHASE0_CONFIG
from pyramid.httpexceptions import HTTPNotFound

def includeme(config):
    def add_dispatched_route(config, route_name, route_pattern, dispatch_with):
        def route_factory(request):
            api = request.find_service(name=dispatch_with)
            obj = api.by_id(request.matchdict["id"])
            if not obj:
                raise HTTPNotFound()
            return obj
        def route_pregenerator(request, elements, kw):
            api = request.find_service(name=dispatch_with)
            try:
                obj = kw.pop(api.get_pregenerator_kw())
            except KeyError:
                pass
            else:
                kw["id"] = obj.id
            return elements, kw
        def register():
            config.add_route(route_name, route_pattern, factory=route_factory, pregenerator=route_pregenerator)
        config.action(('dispatched_route', route_name), register, order=PHASE0_CONFIG)

    config.add_directive('add_dispatched_route', add_dispatched_route)

Pyramid 中的阶段工作方式不允许您对阶段内的操作重新排序。基本上想象一下,每次调用 config.add_route 都会附加到一个列表中,然后迭代该列表以添加路由。您不能在另一个调用之前插入对 config.add_route 的调用。

但是,如果您将对 add_route 的每次调用都包含在您自己的操作中,那么您就有机会推迟一切、排序,然后按照您希望的顺序对每个路由调用 config.add_route .