【问题标题】:A better pattern for ajax loading with pyramid?使用金字塔进行 ajax 加载的更好模式?
【发布时间】:2011-12-21 18:17:24
【问题描述】:

我已经阅读了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 }

我想我特别想知道是否有一种更简洁的方法来覆盖渲染器,然后将其包装在某些东西中,而无需显式调用 render 并确保我得到了正确的 dict 或请求作为参数。谢谢

【问题讨论】:

    标签: python pyramid


    【解决方案1】:

    我建议使用 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
    

    【讨论】:

    • 谢谢,我想过这个问题,但我想我想知道是否有办法简化 renderers.render( ... ) 部分,使其更容易包装......但我想不是
    • 很抱歉,但当我阅读您的问题时,我看不出那条特定的线是如何成为焦点的。无论如何,如果您使用自定义 mako 渲染器作为 json 响应的一部分,那将是相当奇怪的,我不确定您希望它如何变得更漂亮。
    【解决方案2】:

    我不熟悉金字塔或 'r.mako' 所引用的内容,但您可能会在使用自定义函数调用控制器之前挂钩请求,该函数检查请求的 Accepts 标头,寻找 ' text/javascript' 或 'application/json' 作为最重要的 Accepts,然后在请求对象上设置一个标志(或将该方法分解为在您的 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) 并在控制器和渲染器中使用它来确定输出和设置内容类型标题

    【讨论】:

      猜你喜欢
      • 2013-05-09
      • 2012-10-03
      • 1970-01-01
      • 1970-01-01
      • 2011-08-11
      • 2019-07-19
      • 1970-01-01
      • 2021-05-14
      • 2014-07-02
      相关资源
      最近更新 更多