Pyramid中更好的Ajax加载模式?
我看过关于使用不同的渲染器和重写渲染器的内容,但我在想有没有更好的方法来处理这种情况。
现在,在我的视图中,我把一组项目返回给模板:
@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 }
我具体想知道有没有更简单的方法来重写渲染器,然后再把它包裹在某个东西里,而不需要明确调用渲染,也不必确保字典或请求作为参数是正确的。谢谢!
2 个回答
1
我对pyramid不太熟悉,也不知道'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对象。
如果你无法在控制器被调用之前接入pyramid,你可以写一个方便的函数来调用is_json(request),然后在控制器和渲染器中使用这个函数,以确定输出格式并设置内容类型的头信息。
8
我建议使用两个视图,这样可以让你对同一份数据应用不同的“外观和感觉”(响应)。
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