My goal: In Pyramid, to call another view-callable, and to get a Response
object back without knowing any details about that view-callable.
In my Pyramid application, say I have a view "foo" which is defined using a view_config decorator:
@view_config(route_name="foo",
renderer="foo.jinja2")
def foo_view(request):
return {"whereami" : "foo!"}
Now say that I want to route "bar" to a view that does the same thing for the time being, so it internally calls foo_view
and returns its Response:
@view_config(route_name="bar")
def bar_view(request):
return foo_view(request)
...but wait! That doesn't work, since foo_view
doesn't return a Response
, its renderer does.
So, this will work:
@view_config(route_name="bar",
renderer="foo.jinja2")
def bar_view(request):
return foo_view(request)
as it will apply the same renderer as foo_view
did. But this is bad, as I now must repeat myself by copying the renderer value AND having to know the renderer of the view being called.
So, I am going to hope that there is some function available in Pyramid that allows calling another view-callable and getting a Response
object back without knowing or caring how it was rendered:
@view_config(route_name="bar")
def bar_view(request):
response = some_function_that_renders_a_view_callable(foo_view, request)
return response
What would some_function_that_renders_a_view_callable
be?
pyramid.views.render_view
appears to search for a view by name; I don't want to give my views names.
(Note: Returning HTTPFound to cause the client to redirect to the target route is what I am trying avoid. I want to "internally" redirect).
Yep. There is some concerns
Thats why you should not call view from view as function, unless you know what you doing
Pyramid creators did awesome tool for server side redirect - http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/subrequest.html
You can invoking a view with using 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()`
When
/view_one
is visted in a browser, the text printed in the browser pane will be "This came from view_two". Theview_one
view used thepyramid.request.Request.invoke_subrequest()
API to obtain a response from another view (view_two
) within the same application when it executed. It did so by constructing a new request that had a URL that it knew would match theview_two
view registration, and passed that new request along topyramid.request.Request.invoke_subrequest()
. Theview_two
view callable was invoked, and it returned a response. Theview_one
view callable then simply returned the response it obtained from theview_two
view callable.
I was struggling with this as well. I have a solution using the render_to_response method, though I'm sure there's a "more correct" way to do it. Until someone posts it, however, here is how I handled this:
from pyramid.renderers import render_to_response
@view_config(route_name="foo", renderer="foo.mak")
def foo_view(request):
return {'stuff':'things', '_renderer':'foo.mak')
def bar_view(request):
values = foo_view(request)
renderer = values['_renderer']
return render_to_response(renderer,values)
(Pyramid 1.3)
This requires a renderer to be used, but by declaring that renderer in the original view's return values, you can retrieve it in another view without knowing what it is. I'm suspecting the need to do this isn't easily findable because there's other, better methods for accomplishing tasks solved by this solution.
Another shortcoming is that it relies on direct import of the view callable. It would be nice if it could be looked up directly by route.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With