14:Ajax开发与JSON渲染器

现代Web应用程序不仅仅是呈现的HTML。动态页面现在使用JavaScript通过请求服务器数据作为JSON来更新浏览器中的UI。Pyramid用 JSON渲染器 .

背景

正如我们看到的 08:使用模板生成HTML ,视图声明可以指定呈现器。然后通过渲染器运行视图的输出,渲染器生成并返回响应。我们首先使用变色龙渲染器,然后使用Jinja2渲染器。

然而,渲染器并不局限于生成HTML的模板。Pyramid提供了一个JSON渲染器,它获取python数据,将其序列化为JSON,并执行一些其他功能,如设置内容类型。事实上,您可以编写自己的渲染器(或扩展内置渲染器),其中包含用于唯一应用程序的自定义逻辑。

步骤

  1. 首先我们复制 view_classes 步骤:

    cd ..; cp -r view_classes json; cd json
    $VENV/bin/pip install -e .
    
  2. 我们为添加了一条新路线 hello_json 在里面 json/tutorial/__init__.py

     1from pyramid.config import Configurator
     2
     3
     4def main(global_config, **settings):
     5    config = Configurator(settings=settings)
     6    config.include('pyramid_chameleon')
     7    config.add_route('home', '/')
     8    config.add_route('hello', '/howdy')
     9    config.add_route('hello_json', '/howdy.json')
    10    config.scan('.views')
    11    return config.make_wsgi_app()
    
  3. 与其实现一个新视图,我们将在 hello 视图 views.py

     1from pyramid.view import (
     2    view_config,
     3    view_defaults
     4    )
     5
     6
     7@view_defaults(renderer='home.pt')
     8class TutorialViews:
     9    def __init__(self, request):
    10        self.request = request
    11
    12    @view_config(route_name='home')
    13    def home(self):
    14        return {'name': 'Home View'}
    15
    16    @view_config(route_name='hello')
    17    @view_config(route_name='hello_json', renderer='json')
    18    def hello(self):
    19        return {'name': 'Hello View'}
    
  4. 我们在年底需要一个新的功能测试 json/tutorial/tests.py

     1import unittest
     2
     3from pyramid import testing
     4
     5
     6class TutorialViewTests(unittest.TestCase):
     7    def setUp(self):
     8        self.config = testing.setUp()
     9
    10    def tearDown(self):
    11        testing.tearDown()
    12
    13    def test_home(self):
    14        from .views import TutorialViews
    15
    16        request = testing.DummyRequest()
    17        inst = TutorialViews(request)
    18        response = inst.home()
    19        self.assertEqual('Home View', response['name'])
    20
    21    def test_hello(self):
    22        from .views import TutorialViews
    23
    24        request = testing.DummyRequest()
    25        inst = TutorialViews(request)
    26        response = inst.hello()
    27        self.assertEqual('Hello View', response['name'])
    28
    29
    30class TutorialFunctionalTests(unittest.TestCase):
    31    def setUp(self):
    32        from tutorial import main
    33        app = main({})
    34        from webtest import TestApp
    35
    36        self.testapp = TestApp(app)
    37
    38    def test_home(self):
    39        res = self.testapp.get('/', status=200)
    40        self.assertIn(b'<h1>Hi Home View', res.body)
    41
    42    def test_hello(self):
    43        res = self.testapp.get('/howdy', status=200)
    44        self.assertIn(b'<h1>Hi Hello View', res.body)
    45
    46    def test_hello_json(self):
    47        res = self.testapp.get('/howdy.json', status=200)
    48        self.assertIn(b'{"name": "Hello View"}', res.body)
    49        self.assertEqual(res.content_type, 'application/json')
    50
    
  5. 运行测试:

    $VENV/bin/pytest tutorial/tests.py -q
    .....
    5 passed in 0.47 seconds
    
  6. 运行 Pyramid 应用程序时使用:

    $VENV/bin/pserve development.ini --reload
    
  7. 在浏览器中打开http://localhost:6543/howdy.json,您将看到结果的json响应。

分析

之前,我们更改了视图函数和方法以返回Python数据。这种对面向数据的视图层的更改使测试编写更加容易,从而将模板化与视图逻辑分离开来。

由于Pyramid有一个JSON渲染器和模板化渲染器,返回JSON是一个简单的步骤。在这种情况下,我们保持完全相同的视图,并安排返回视图数据的JSON编码。我们这样做是:

  • 向地图添加路线 /howdy.json 到路由名称。

  • 提供一个 @view_config 将该路由名称与现有视图关联的。

  • 压倒一切 视图配置中提到 hello_json 路由,这样当路由匹配时,我们使用JSON呈现器而不是 home.pt 否则将使用的模板呈现器。

事实上,对于纯Ajax风格的Web应用程序,我们可以通过使用Pyramid的视图谓词来匹配 Accepts: 由现代Ajax实现发送的头。

Pyramid的JSON渲染器使用基本的python JSON编码器,从而继承了它的优点和缺点。例如,python不能本机对datetime对象进行JSON编码。在Pyramid中有许多解决方案,包括使用自定义渲染器扩展JSON渲染器。