使用自定义指令/操作时路由匹配的控制顺序
Posted
技术标签:
【中文标题】使用自定义指令/操作时路由匹配的控制顺序【英文标题】:control order that routes are matched when using a custom directive/action 【发布时间】:2022-01-17 08:39:31 【问题描述】:我有一个包罗万象的路由,它在我调用 add_route 之前在使用自定义指令创建的操作中捕获我的请求。我怎样才能防止这种情况发生? IE。手动将包罗万象的路由放在路由匹配过程的末尾,还是将我的操作的 add_route 放在路由匹配过程的前面?
我尝试在admin/routes.py
和routes.py
之间交换includes
的顺序,但这似乎没有影响。一个快速的解决方案(现在考虑它可能是个好主意)是从包罗万象的模式中过滤管理员。但我觉得这会再次出现,我无法做到这一点,所以我问这个问题。
__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)
【问题讨论】:
包罗万象的路线应该是最后声明的路线。尝试将其移到for k in (".customer", ".admin"):
块之后。您可能需要将 routes.py
拆分为两个文件,一个在开头包含所有文件,另一个在末尾包含 catchall.py
。
@StevePiercy 我喜欢明确的包罗万象文件的想法,所以我尝试了它,但它似乎不起作用。似乎该操作在所有其他 add_route 调用发生之后注册 add_route ,即使对指令的调用发生在包含 catchall 文件之前。这是一种边缘情况,因为包罗万象的情况非常罕见。我无法控制动作的顺序,因为我本质上是通过调用 add_route 来调用另一个动作。我将只实现一个非框架解决方案。
【参考方案1】:
阶段在 Pyramid 中的工作方式不允许您对阶段内的操作重新排序。基本上想象每次对config.add_route
的调用都被附加到一个列表中,然后迭代该列表以添加路由。您不能在另一个调用之前注入对 config.add_route
的调用。
但是,如果您将每次对 add_route 的调用都包含在自己的操作中,那么您就有机会推迟所有内容、订购东西,然后按照您希望的顺序对每个路由调用 config.add_route
。
【讨论】:
我最终只是按照您的建议将所有内容包装在我自己的 add_route 中,并且有效。以上是关于使用自定义指令/操作时路由匹配的控制顺序的主要内容,如果未能解决你的问题,请参考以下文章