20
# /test{.format} no longer seems to work...
config.add_route('test', '/test.{ext}', view='ms.views.test')

视图.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)

有没有更简单的方法来做到这一点?使用 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')

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

4

4 回答 4

51

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

def my_view(request):
    return {"message": "Hello, world!"}

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

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)

我们现在拥有的:

  1. 如果我们将浏览器指向 url,Viewmy_view将使用作为上下文提供的返回 dict 呈现模板。"templates/my_template.mako"/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")

现在/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")

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

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

于 2011-01-08T13:26:19.837 回答
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) )
于 2011-01-08T12:46:20.557 回答
2

PyramidURL Dispatch是非常强大和灵活的机制。首先,我们将编写正确的 url 模式。在路由模式语法中,我们可以使用正则表达式来替换标记。

'/test{ext:\\..*}'

在这里我们可以看到 url 路径应该包含 . (句点),然后是任何符号。所有符号,包括 . (句点)将在 中的键extrequest.matchdict

当然,我们可以使正则表达式复杂化,以指定可能有哪些扩展:

'/test{ext:\\.(html|json)}'

然后我们用我们的模式添加路由:

config.add_route('test',
                 pattern='/test{ext:\\.(html|json)}')

要补充的是,我们可以使用自定义谓词指定扩展集。

为了指定默认扩展,我们可以使用简单的pregenerator

def default_extension(ext):
    def pregenerator(request, elements, kw):
        if 'ext' not in kw:
            kw['ext'] = ext

        return elements, kw

    return pregenerator

config.add_route('test',
                 pattern='/test{ext:\\.(html|json)}',
                 pregenerator=default_extension('.html'))

request.route_path('test')
# '/test.html'
request.route_path('test', ext='.json')
# '/test.json'

之后,我们将Traversal帮助我们在htmljson输出之间切换:

config.add_route('test',
                 '/test{ext:\\.(html|json)}',
                 pregenerator=default_extension('.html'),
                 traverse='{ext}')

使用中的traverse论点,add_route我们强制我们的应用程序是混合的。我们应该明白,为我们的视图提供上下文的工厂不能包含与我们的扩展匹配的键。默认的根工厂没有。

视图.py:

from pyramid.view import view_config, view_defaults


@view_defaults(route_name='test')
class Test(object):
    def __init__(self, request):
        self.request = request
        self.variables = {
            'name': 'blah',
            'asd': 'sdf'
        }

    @view_config(name='.html', renderer='mypackage:templates/blah.pt')
    def html(request):
        return {
            'request': request,
            'variables': self.variables
        }

    @view_config(name='.json', renderer='json')
    def json(request):
        return {
            'request': request,
            'variables': self.variables
        }

在这里,我们class Test为它创建并指定了路由名称。然后我们通过扩展名分隔方法。

于 2013-10-03T10:02:56.577 回答
0

试试这个方法:

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

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

    return render_to_response('/templates/blah.html')

这与您的 pylons 示例最相似。它还显示了一些更友好的方式来呈现模板或一些 JSON 到响应。

于 2014-02-18T23:49:29.760 回答