我已经阅读了using different renderers或overriding renderer,但我想知道是否有更好的方法来处理这种模式。
现在,在我看来,我正在向模板返回一组项目:
@view_config(
route_name = 'name',
permission = 'perm',
renderer = 'r.mako'
)
def r( request ):
items = get_items()
return { 'items': items }
现在我希望ajax版本只渲染它的一个子集,也包含一些数据。我目前的工作代码:
@view_config(
route_name = 'name',
permission = 'perm',
renderer = 'r.mako'
)
def r( request ):
items = get_items()
if ajax:
return Response( to_json( {
'data1': 1,
'data2': 2,
'data3': 3,
'html': renderers.render( 'shortr.mako',
{ 'items': items },
request )
} )
return { 'items': items }
我想我特别想知道是否有更简洁的方法来覆盖渲染器,然后将其包装在某个东西中,而不显式调用渲染并确保我得到了正确的dict或请求作为参数。感谢
答案 0 :(得分:8)
我建议使用2个视图,这些视图可以正确地允许您对同一数据应用不同的“外观”(响应)。
def get_items(request):
return {} # values that you can pick and choose from in each view
@view_config(route_name='name', permission='perm', xhr=True, renderer='json')
def r_ajax(request):
items = get_items(request)
return {
'data1': 1, 'data2': 2, 'data3': 3,
'html': renderers.render('shortr.mako', {'items': items}, request),
}
@view_config(route_name='name', permission='perm', renderer='r.mako')
def r_html(request):
items = get_items(request)
return items
如果你害怕为视图配置重复一些事情,那么Pyramid 1.3在其基于类的视图上提供了一个很酷的新功能:
@view_defaults(route_name='name', permission='perm')
class R(object):
def __init__(self, request):
self.request = request
self.items = # ...
@view_config(xhr=True, renderer='json')
def ajax(request):
return {
'data1': 1, 'data2': 2, 'data3': 3,
'html': renderers.render('shortr.mako', {'items': items}, request),
}
@view_config(renderer='r.mako')
def html(request):
return self.items
答案 1 :(得分:1)
我不熟悉金字塔或者什么' r.mako'正在引用,但您可以在使用自定义函数调用控制器之前挂钩请求,该自定义函数检查请求的Accepts标头,查找&text; javascript'或者' application / json'作为最重要的接受,然后在请求对象上设置一个标志(或将该方法考虑在你的r函数中使用)。
然后执行自定义渲染器来处理使用mako解析或转储json字符串
# pseudo-code
def before_controller(request, response):
if 'text/html' in request.headers.accepts:
request.is_json = False
elif 'application/json' in request.headers.accepts:
response.headers.set('Content-type', 'application/json')
request.is_json = True
# pseudo-code
def my_renderer(request, response, result):
if 'text/html' in request.headers.accepts:
return # render html
elif 'application/json' in request.headers.accepts:
response.headers.set('Content-type', 'application/json')
return json.dumps(result)
#
def r(request):
items = get_items()
if request.json:
pass # update items with additional data
return {'items': items} # one point of return
如果您不需要对项目进行任何额外处理,该方法也意味着没有额外的腿部工作,您只需正常返回结果并在另一端接收json对象。
如果在调用控制器之前无法挂入金字塔,可以编写一个方便函数来调用is_json(request)并在控制器和渲染器中使用它来确定输出和设置内容类型标题