08:使用模板生成HTML¶
大多数Web框架不在编程代码中嵌入HTML。相反,它们将数据传递到模板系统中。在这一步中,我们将了解在Pyramid中使用HTML模板的基础知识。
背景¶
哎哟。我们一直在创造自己的 Response
并用HTML填充响应体。通常不会将HTML字符串直接嵌入到Python中,而是使用模板语言。
Pyramid并不要求特定的数据库系统、表单库等。它鼓励可替换性。这同样适用于模板化,这是幸运的:开发人员对模板语言有很强的看法。对于Pyramid1.5A2,Pyramid甚至不捆绑模板语言!
然而,它确实与Jinja2、Mako和变色龙有着密切的联系。在这一步中,我们将看到如何添加 pyramid_chameleon 到项目,然后更改视图以使用模板。
目标¶
启用
pyramid_chameleon
Pyramid附加。从模板文件生成HTML。
将模板连接为视图代码的“渲染器”。
将视图代码更改为只返回数据。
步骤¶
让我们从使用前一个包作为新项目的起点开始:
cd ..; cp -r views templating; cd templating
这一步取决于
pyramid_chameleon
,因此将其作为依赖项添加到templating/setup.py
:1from setuptools import setup 2 3# List of dependencies installed via `pip install -e .` 4# by virtue of the Setuptools `install_requires` value below. 5requires = [ 6 'pyramid', 7 'pyramid_chameleon', 8 'waitress', 9] 10 11# List of dependencies installed via `pip install -e ".[dev]"` 12# by virtue of the Setuptools `extras_require` value in the Python 13# dictionary below. 14dev_requires = [ 15 'pyramid_debugtoolbar', 16 'pytest', 17 'webtest', 18] 19 20setup( 21 name='tutorial', 22 install_requires=requires, 23 extras_require={ 24 'dev': dev_requires, 25 }, 26 entry_points={ 27 'paste.app_factory': [ 28 'main = tutorial:main' 29 ], 30 }, 31)
现在我们可以激活开发模式分布:
$VENV/bin/pip install -e .
我们需要连接
pyramid_chameleon
作为渲染器调用templating/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.scan('.views') 10 return config.make_wsgi_app()
我们的
templating/tutorial/views.py
不再包含HTML:1from pyramid.view import view_config 2 3 4# First view, available at http://localhost:6543/ 5@view_config(route_name='home', renderer='home.pt') 6def home(request): 7 return {'name': 'Home View'} 8 9 10# /howdy 11@view_config(route_name='hello', renderer='home.pt') 12def hello(request): 13 return {'name': 'Hello View'}
相反,我们有
templating/tutorial/home.pt
作为模板:<!DOCTYPE html> <html lang="en"> <head> <title>Quick Tutorial: ${name}</title> </head> <body> <h1>Hi ${name}</h1> </body> </html>
为方便起见,更改
templating/development.ini
自动重新加载模板的步骤pyramid.reload_templates
:[app:main] use = egg:tutorial pyramid.reload_templates = true pyramid.includes = pyramid_debugtoolbar [server:main] use = egg:waitress#main listen = localhost:6543
我们的单元测试
templating/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 home 15 16 request = testing.DummyRequest() 17 response = home(request) 18 # Our view now returns data 19 self.assertEqual('Home View', response['name']) 20 21 def test_hello(self): 22 from .views import hello 23 24 request = testing.DummyRequest() 25 response = hello(request) 26 # Our view now returns data 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)
现在运行测试:
$VENV/bin/pytest tutorial/tests.py -q .... 4 passed in 0.46 seconds
运行 Pyramid 应用程序时使用:
$VENV/bin/pserve development.ini --reload
在浏览器中打开http://localhost:6543/和http://localhost:6543/howdy。
分析¶
啊,看起来好多了。我们有一个关注Python代码的视图。我们的 @view_config
decorator指定 renderer 指向我们的模板文件。然后,我们的视图只返回数据,这些数据随后被提供给我们的模板。请注意,我们对两个视图使用了相同的模板。
注意对测试的影响。我们可以集中精力与视图代码签订面向数据的契约。
参见
模板 , 调试模板 和 可用的附加模板系统绑定 .