ajax加载金字塔的更好模式?

时间:2011-12-21 18:17:24

标签: python pyramid

我已经阅读了using different renderersoverriding 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或请求作为参数。感谢

2 个答案:

答案 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)并在控制器和渲染器中使用它来确定输出和设置内容类型标题