使用自定义 directive/action 时路由匹配的控制顺序
control order that routes are matched when using a custom directive/action
在使用自定义指令创建的操作中调用 add_route 之前,我有一个 catchall 路由捕获我的请求。我怎样才能防止这种情况发生? IE。手动将 catchall 路由放在路由匹配过程的末尾,或者将我的操作 add_route 放在路由匹配过程的前面?
我尝试在 admin/routes.py
和 routes.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
.
在使用自定义指令创建的操作中调用 add_route 之前,我有一个 catchall 路由捕获我的请求。我怎样才能防止这种情况发生? IE。手动将 catchall 路由放在路由匹配过程的末尾,或者将我的操作 add_route 放在路由匹配过程的前面?
我尝试在 admin/routes.py
和 routes.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
.