在Python Pyramid路由配置中使用查询字符串

6 投票
3 回答
3161 浏览
提问于 2025-04-16 22:38

这段内容是关于我正在做的一个具体项目,所以我来描述一下它的情况:

  • 这是一个Pyramid应用程序,用来展示图表,比如这个链接:http://localhost:6543/path/to/myplot/plot001.png
  • 如果这个图表不可用,就会显示另一张图片(work.png)
  • 还有一个部分是deform视图,它提供了一个HTML表单,可以输入图表的配置,比如:http://localhost:6543/path/to/myplot/plot001.png?action=edit。这里需要注意的是查询字符串“action=edit”。
  • 这个配置包括数据文件、模板等等。
  • 表单有保存按钮(用来保存配置)和渲染按钮(http://localhost:6543/path/to/myplot/plot001.png?action=render)。渲染的结果会生成一个png文件,然后以静态方式使用。

我已经搞清楚了很多细节,比如如何使用Matplotlib进行渲染等等,但我对Pyramid和Deform还不太熟悉。我也有一个可以从文件中展示图表的视图。deform表单也能基本工作。目前我不太清楚如何最好地结构化URL,以区分展示、编辑和渲染这几种用法。我想在Pyramid中,这意味着如何配置serve_view和edit_view的路由。

__init__.py:
    config.add_route('serve_route', 
        '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')
    config.add_route('edit_route', 
        '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')
# can I use query strings like "?action=edit" here to distinguish the difference?


views.py:
@view_config(context=Root, route_name='serve_route')
def plot_view(context, request):
... 
@view_config(context=Root, renderer='bunseki:templates/form.pt', route_name='edit_route')
def edit_view(request):
...

在Pyramid手册中,我找不到关于如何在路由中设置参数的说明。我想如果能指向一些文档或示例就足够了,我可以自己搞定细节。谢谢!

3 个回答

0

一种更有效的方法是直接在网址里指定你想要的操作。你甚至可以在同一个路由名称上提供不同的操作,或者多个操作。

config.add_route('serve_route', '/{project_name}/testruns/{testrun_name}/plots/{action}/{plot_name}.png')

views.py
@view_config(context=Root, route_name='serve_route', action='view')
def plot_view(request):
    pass

或者使用查询字符串

`config.add_route('serve_route', 
    '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')

views.py
@view_config(context=Root, route_name='serve_route')
def plot_view(request):
    try:
       action = getattr(self._request.GET, 'action')
    except AttributeError:
       raise 
1

我不太确定在这种情况下是否可以使用 contex=Root,但你问的内容可能是 matchdict

__init__.py:

config.add_route('serve_route', 
    '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')

views.py:

@view_config(route_name='serve_route')
def plot_view(request):
    project_name = request.matchdict['project_name']
    action = request.params.get('action', None)

http://docs.pylonsproject.org/projects/pyramid/1.1/narr/urldispatch.html#matchdict

补充:

如果你的问题更像是关于路由的一般性问题,你应该为每个操作创建一个路由,这样可以让你的视图函数代码更简洁明了。例如,如果你想进行编辑和渲染,你的路由可以像这样:

__init__.py:

config.add_route('render_plot',
    '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')
config.add_route('edit_plot',
    '/{project_name}/testruns/{testrun_name}/plots/{plot_name}/edit')

views.py:

@view_config('render_plot')
def render(request):
    pass

@view_config('edit_plot', renderer='bunseki:templates/form.pt')
def edit(request):
    pass
12

根据你喜欢的代码分隔方式,有两种方法可以做到这一点。

  1. 把所有的逻辑放在你的视图里,用 'if' 语句来区分 request.GET.get('action') 的不同情况。

    config.add_route('plot', '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')
    config.scan()
    
    @view_config(route_name='plot')
    def plot_view(request):
        action = request.GET('action')
        if action == 'edit':
            # do something
            return render_to_response('bunseki:templates/form.pt', {}, request)
    
        # return the png
    
  2. 注册多个视图,然后通过 Pyramid 的视图查找机制在它们之间进行切换。

    config.add_route('plot', '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')
    config.scan()
    
    @view_config(route_name='plot')
    def plot_image_view(request):
        # return the plot image
    
    @view_config(route_name='plot', request_param='action=edit',
                 renderer='bunseki:templates/form.pt')
    def edit_plot_view(request):
        # edit the plot
        return {}
    
    # etc..
    

希望这对你有帮助。这是一个很好的例子,展示了如何注册一个单一的 URL 模式,并对该 URL 的不同请求使用不同的视图。

撰写回答