使用金字塔进行 ajax 加载有更好的模式吗?

发布于 2024-12-22 20:11:29 字数 1300 浏览 0 评论 0原文

我读过 使用不同的渲染器重写渲染器但我我想知道是否有更好的方法来处理这种模式。

现在,在我看来,我正在向模板返回一组项目:

@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 }

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

I've read up on using different renderers or overriding renderer but I'm wondering if there's a better way to handle this pattern.

Right now, in my view I'm returning a set of items to the template:

@view_config(
    route_name = 'name',
    permission = 'perm',
    renderer   = 'r.mako'
)
def r( request ):
     items = get_items()
     return { 'items': items }

Now I want the ajax version to just renderer a subset of it, also with some data. My current working code:

@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 }

I guess specifically I wonder if there's a cleaner way to override the renderer and then wrap it in something, without explicitly calling render and making sure I got the dict right or request as a param. thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

高跟鞋的旋律 2024-12-29 20:11:29

我建议使用两个视图,它们可以正确地允许您对相同的数据应用不同的“外观和感觉”(响应)。

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

I would suggest using 2 views which properly allow you to apply a different "look-and-feel" (responses) to the same data.

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

If you're afraid of repeating things for the view configuration, Pyramid 1.3 comes with a cool new feature on its class-based views:

@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
年华零落成诗 2024-12-29 20:11:29

我不熟悉金字塔或“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) 并在控制器和渲染器中使用它来确定输出并设置内容类型标头

I'm not familiar with pyramid or what 'r.mako' is referencing, but you could probably hook in to the request before the controller is called with a custom function that inspects the Accepts headers of the request, looking for 'text/javascript' or 'application/json' as the foremost Accepts, and then set a flag on the request object (or have that method factored out for use in your r function).

Then do a custom renderer to handle either parsing with mako or dumping a json string

# 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

The method would also mean no extra leg-work if you dont need to do any additional processing on items, you simply return the result as normal and receive the json object on the other end.

If you cant hook into pyramid before the controller is called, you could write a convenience function to call is_json(request) and use that in the controller and the renderer for determining output and setting content-type header

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文