有没有更好的方法在Pyramid中切换HTML和JSON输出?

dav*_*ave 20 python api pylons pyramid

# /test{.format} no longer seems to work...
config.add_route('test', '/test.{ext}', view='ms.views.test')
Run Code Online (Sandbox Code Playgroud)

views.py:

from pyramid.response import Response
from pyramid.renderers import render

import json

def test(request):
    extension = request.matchdict['ext']
    variables = {'name' : 'blah', 'asd' : 'sdf'}

    if extension == 'html':
        output = render('mypackage:templates/blah.pt', variables, request=request)

    if extension == 'json':
        output = json.dumps(variables)

    return Response(output)
Run Code Online (Sandbox Code Playgroud)

有更简单的方法吗?有了Pylons,它很简单:

def test(self, format='html'):
    c.variables = {'a' : '1', 'b' : '2'}

    if format == 'json':
        return json.dumps(c.variables)

    return render('/templates/blah.html')
Run Code Online (Sandbox Code Playgroud)

我怀疑我接近这个错误的方式......?

and*_*opp 51

我认为,更好的方法是使用差异渲染器两次添加相同的视图.假设我们有以下观点:

def my_view(request):
    return {"message": "Hello, world!"}
Run Code Online (Sandbox Code Playgroud)

现在在我们的配置中,我们可以添加两次相同的视图:

from pyramid.config import Configurator
config = Configurator()
config.add_route('test', '/test', my_view, renderer="templates/my_template.mako")
config.add_route('test', '/test', my_view, renderer="json", xhr=True)
Run Code Online (Sandbox Code Playgroud)

我们现在拥有的:

  1. 如果我们将浏览器指向url,View my_view将以"templates/my_template.mako"返回的dict作为上下文呈现模板/test.
  2. 如果我们将my_view再次调用XHR请求,但现在返回的dict将被编码为JSON并传回给调用者(请阅读有关检查请求是否通过XHR完成的文档).

我们可以使用相同的想法来定义不同的路线,但附加相同的视图:

from pyramid.config import Configurator
config = Configurator()
config.add_route('test', '/test', my_view, renderer="templates/my_template.mako")
config.add_route('test_json', '/test.json', my_view, renderer="json")
Run Code Online (Sandbox Code Playgroud)

现在/test将触发模板渲染,但/test.json只会返回JSON编码的字符串.

您可以进一步通过方法accept参数调度到正确的渲染器add_router:

from pyramid.config import Configurator
config = Configurator()
config.add_route('test', '/test', my_view, renderer="templates/my_template.mako")
config.add_route('test', '/test', my_view, renderer="json", accept="application/json")
Run Code Online (Sandbox Code Playgroud)

如果请求自带标头Accept设置为application/json值,则返回JSON,否则您将获得渲染模板.

请注意,只有在您希望对视图中的响应进行编码的预定义数据格式集时,这才有效,但这是常见的情况.如果您需要动态调度,您可以使用decorate参数装饰您的视图,该参数add_route将根据您的规则选择正确的渲染器.

  • +1我认为这最好地反映了做事的"金字塔方式".它是灵活的,将视图与渲染器分离,使视图更容易进行单元测试,因为您可以只搜索字典中的值,而不是解析html文档. (3认同)

S.L*_*ott 6

这是你在找什么?Pylons和Pyramid有不同的API.所以他们会有所不同.你可以让它们更相似,但你不能让它们相同.

def test(request):
    extension = request.matchdict['ext']
    variables = {'name' : 'blah', 'asd' : 'sdf'}

    if extension == 'json':
        return Response( json.dumps(variables) )

    return Response( render('mypackage:templates/blah.pt', variables, request=request) )
Run Code Online (Sandbox Code Playgroud)