在金字塔中调用另一个视图

kes*_*kes 14 python view pyramid

我的目标:在金字塔中,调用另一个视图可调用,并在Response不知道有关该视图可调用的任何细节的情况下获取对象.

在我的Pyramid应用程序中,假设我有一个使用view_config装饰器定义的视图"foo":

@view_config(route_name="foo",
             renderer="foo.jinja2")
def foo_view(request):
    return {"whereami" : "foo!"}
Run Code Online (Sandbox Code Playgroud)

现在说我想将"bar"路由到暂时执行相同操作的视图,因此它在内部调用foo_view并返回其响应:

@view_config(route_name="bar")
def bar_view(request):
   return foo_view(request)
Run Code Online (Sandbox Code Playgroud)

...可是等等!这不起作用,因为foo_view它不会返回Response它的渲染器.

所以,这将工作:

@view_config(route_name="bar",
             renderer="foo.jinja2")
def bar_view(request):
    return foo_view(request)
Run Code Online (Sandbox Code Playgroud)

因为它将应用相同的渲染器foo_view.但这很糟糕,因为我现在必须通过复制渲染器值并且必须知道被调用视图的渲染器来重复自己.

所以,我希望Pyramid中有一些函数允许调用另一个view-callable并在Response不知道或关心渲染对象的情况下获取一个对象:

@view_config(route_name="bar")
def bar_view(request):
    response = some_function_that_renders_a_view_callable(foo_view, request)
    return response
Run Code Online (Sandbox Code Playgroud)

some_function_that_renders_a_view_callable是什么?

pyramid.views.render_view似乎按名称搜索视图; 我不想透露姓名.

(注意:返回HTTPFound导致客户端重定向到目标路由是我试图避免的.我想"内部"重定向).

eno*_*mad 8

是的.有一些顾虑

  • 不会返回响应
  • 谓词/渲染器
  • 权限
  • 请求与旧请求关联的属性

这就是为什么你不应该从视图中调用视图作为函数,除非你知道你在做什么

金字塔创建者为服务器端重定向做了很棒的工具 - http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/subrequest.html


Ano*_*ari 6

您可以使用以下方式调用视图request.invoke_subrequest

from wsgiref.simple_server import make_server

from pyramid.config import Configurator

from pyramid.request import Request


def view_one(request):

    subreq = Request.blank('/view_two')
    response = request.invoke_subrequest(subreq)
    return response

def view_two(request):

    request.response.body = 'This came from view_two'
    return request.response

if __name__ == '__main__':

    config = Configurator()
    config.add_route('one', '/view_one')
    config.add_route('two', '/view_two')
    config.add_view(view_one, route_name='one')
    config.add_view(view_two, route_name='two')
    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()`
Run Code Online (Sandbox Code Playgroud)

/view_one在浏览器中访问时,浏览器窗格中打印的文本将为“This come from view_two”。该view_one视图在执行时使用pyramid.request.Request.invoke_subrequest()API 从同一应用程序内的另一个视图 ( ) 获取响应。view_two它通过构造一个新请求来实现这一点,该请求具有一个它知道与view_two视图注册相匹配的 URL,并将该新请求传递给 pyramid.request.Request.invoke_subrequest(). 可调用视图view_two被调用,并且它返回了响应。然后,可调用视图view_one简单地返回从可调用视图获得的响应 view_two


Mar*_*ill 3

此处的金字塔文档表明,将name关键字参数排除在外view_config将导致视图由函数本身(而不是字符串)注册:

这样的注册...意味着视图名称将是 *my_view*

因此,在您的情况下,您应该能够直接使用pyramid.view.render_viewpyramid.view.render_view_to_response引用:foo_view

@view_config(route_name="bar")
def bar_view(request):
    return pyramid.views.render_view_to_response(None, request, name=foo_view)
Run Code Online (Sandbox Code Playgroud)

更新:

是的,你说得对,传递视图函数不起作用

这很有趣,但是采用您的示例代码并将其应用于route_name配置对我来说不起作用。但是,下面的示例仅给视图设置name了路由 url 并为视图提供了名称。以这种方式,render_view_to_response正如广告所宣传的那样。命名,您的视图可能不是您想要的,但是此配置可以完成与示例代码相同的事情,而无需添加配置。

@view_config(name="foo")
def foo_view(request):
    # returning a response here, in lieu of having
    # declared a renderer to delegate to...
    return Response('Where am i? `{0[whereami]}'.format({"whereami" : "foo!"}))

@view_config(name="bar")
def bar_view(request):
    # handles the response if bar_view has a renderer 
    return render_view_to_response(None, request, name='foo')

@view_config(name="baz")
def baz_view(request):
    # presumably this would not work if foo_view was
    # not returning a Response object directly, as it
    # skips over the rendering part. I think you would
    # have to declare a renderer on this view in that case.
    return foo_view(request)

if __name__ == '__main__':
    config = Configurator()
    config.scan()
    app = config.make_wsgi_app()
    serve(app, host='127.0.0.1', port='5000')
Run Code Online (Sandbox Code Playgroud)