Python Pyramid 简明教程
Python Pyramid - Templates
默认情况下,视图函数的响应的内容类型为纯文本。为了呈现 HTML,响应主体文本可能包括 HTML 标签,如下例所示 −
Example
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
def hello_world(request):
return Response('<h1 style="text-align:center;">Hello World!</h1>')
if __name__ == '__main__':
with Configurator() as config:
config.add_route('hello', '/')
config.add_view(hello_world, route_name='hello')
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()
Output
在启动服务器(通过运行以上代码)之后,访问 http://localhost:6543/ ,浏览器渲染以下输出 −
但是,这种渲染 HTML 的方法,尤其是如果它可能包含某些可变数据,是极其繁琐的。出于此目的,Web 框架使用模板库。模板库将可变数据与其他静态 HTML 代码合并,以动态生成和呈现网页。
Template Bindings
Pyramid 提供了使用诸如 jinja2、Mako 和 Chameleon 等流行模板库的绑定来提供模板支持。
Template Language |
Pyramid Bindings |
Default Extensions |
Chameleon |
pyramid_chameleon |
.pt, .txt |
Jinja2 |
pyramid_jinja2 |
.jinja2 |
Mako |
pyramid_mako |
.mak, .mako |
首先,我们需要为使用所需的模板库安装相应的 Python 库。例如,要使用 jinja2 模板,请使用 PIP 安装程序安装 pyramid_jinja2 。
pip3 install pyramid_jinja2
然后,我们需要将其包含在应用程序配置中。
config.include('pyramid_jinja2')
pyramid.renderers 模块定义了 render_to_response() 函数。它与以下参数一起使用 −
render_to_response(renderer_name, value, request)
renderer_name 是模板网页,通常保存在应用程序目录的子文件夹 templates 中,value 参数是作为上下文传递给模板的字典,以及从 WSGI 环境中获取的请求对象。
将以下 HTML 脚本另存为 hello.jinja2 目录中的 templates 。
<html>
<body>
<h1>Hello, {{ name }}!</h1>
</body>
</html>
Rendering Template
hello_world() 视图函数通过调用 render_to_response() 函数直接呈现此模板。它还将上下文值发送到模板。
from pyramid.renderers import render_to_response
def hello_world(request):
return render_to_response('templates/hello.jinja2',{'name':'Tutorialspoint'},
request=request)
Example
与往常一样,此视图被添加到 hello 路由,指向 / URL。完整的应用程序代码如下 −
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.renderers import render_to_response
def hello_world(request):
return render_to_response('templates/hello.jinja2', {'name':'Tutorialspoint'}, request=request)
if __name__ == '__main__':
with Configurator() as config:
config.add_route('hello', '/')
config.include('pyramid_jinja2')
config.add_view(hello_world, route_name='hello')
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()
Output
运行服务器并访问 http://localhost:6543/ 。浏览器显示以下结果 −
每个视图都返回一个响应对象。 render_to_response() 函数是一个快捷函数,实际上返回一个响应对象。这允许上面的 hello_world 视图直接返回其对 render_to_response() 的调用的结果。
另一方面, pyramid.renderers.render() 函数将模板渲染为字符串。我们可以直接生成一个响应对象,并使用该字符串作为响应的主体。
让我们按如下方式更改 hello_world() 视图函数 −
from pyramid.renderers import render
def hello_world(request):
retval = render('templates/hello.jinja2',
{'name':'Tutorialspoint'}, request=request)
return Response(retval)
其余代码保持不变,浏览器也显示与上面相同的输出。
Rendering via Configuration
正如前面提到的,Pyramid 的视图可调用 id 返回的 HTTP 响应的 content_type 是 text/plain。但是,如果 @view_config 装饰器的 renderer 参数被分配了其中任何一个值,它可以被更改为字符串、JSON 或 JSONP。因此,Pyramid 具有以下内置渲染器 −
-
JSON
-
String
-
JSONP
Example
在以下示例中,hello_world() 视图函数被配置为渲染 JSON 响应。
from pyramid.view import view_config
@view_config(route_name='hello',renderer='json')
def hello_world(request):
return {'content':'Hello World!'}
Output
将 renderer 类型设置为 JSON 也将 HTTP 响应的 content_type 标头设置为 application/json 。浏览器显示 JSON 响应,如下图所示 −
@view_config() 装饰器的 renderer 参数可以设置为模板网页(它必须存在于 templates 文件夹中)。先决条件是模板库的适当 Python 绑定必须已安装,并且应用程序配置必须包括绑定。
我们已经安装了 python_jinja2 包,这样我们就可以使用 jinja2 模板由 hello_world() 视图函数渲染,该函数由带有 renderer 参数的 @view_config() 装饰。
hello.jinja2 模板 HTML 代码如下 −
<html>
<body>
<h1>Hello, {{ name }}!</h1>
</body>
</html>
经过装饰的 hello_world() 函数被写为 −
from pyramid.view import view_config
@view_config(route_name='hello', renderer='templates/hello.jinja2')
def hello_world(request):
return {'name':'Pyramid!'}
Example
在这种情况下,视图函数返回一个字典对象。它可作为上下文数据提供给模板,它可以在 HTML 文本中借助模板语言语法元素插入。
渲染 jinja2 模板的完整代码如下 −
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.view import view_config
@view_config(route_name='hello', renderer='templates/hello.jinja2')
def hello_world(request):
return {'name':'Pyramid!'}
if __name__ == '__main__':
with Configurator() as config:
config.include('pyramid_jinja2')
config.add_route('hello', '/')
config.scan()
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()
Add/Change Renderer
模板只不过是散布着模板语言语法的网页。尽管 Pyramid 使用 ".jinja2" 作为 jinja2 模板的默认扩展名,但惯例是使用 ".html" 扩展名作为网页。
我们可以更改应用程序配置以添加使用 ".html" 扩展名。这是通过 add_jinja2_renderer 完成的。
config.add_jinja2_renderer(".html")
hello.jinja2 模板现在被重命名为 hello.html。为了能够使用此模板,让我们将视图函数的定义更改为以下代码 −
from pyramid.view import view_config
@view_config(route_name='hello', renderer='templates/hello.html')
def hello_world(request):
return {'name':'Pyramid!'}
同时,通过添加 ".html" 渲染器来修改 Configurator 对象的属性。
if __name__ == '__main__':
with Configurator() as config:
config.include('pyramid_jinja2')
config.add_jinja2_renderer(".html")
config.add_route(hello, '/')
config.scan()
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()
Template Context from matchdict
如前所述,如果路由配置中的 URL 模式包含一个或多个占位符参数,它们从请求 URL 中的值将与请求一起作为 matchdict 对象传递,而该对象反过来可以作为上下文数据传递给要渲染的模板。
对于我们的下一个示例, hello.html - Jinja2 模板保持不变。
<html>
<body>
<h1>Hello, {{ name }}!</h1>
</body>
</html>
我们知道上下文变量 'name' 的值由视图函数传递。但是,我们并不是传递一个硬编码值(如前一个示例中所示),而是从 matchict 对象中获取它的值。此对象是由 URL 字符串中的路径参数填充的。
from pyramid.view import view_config
@view_config(route_name='index', renderer='templates/hello.html')
def index(request):
return {'name':request.matchdict['name']}
Example
修改后的应用程序代码如下所示 −
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.view import view_config
@view_config(route_name='index', renderer='templates/hello.html')
def index(request):
return {'name':request.matchdict['name']}
if __name__ == '__main__':
with Configurator() as config:
config.include('pyramid_jinja2')
config.add_jinja2_renderer(".html")
config.add_route('index', '/{name}')
config.scan()
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()
Output
启动服务器,打开浏览器,输入 URL http://localhost:6543/Tutorialspoint 。结尾字符串成为 matchdict 中 'name' 键的值。它被 Jinja2 模板使用,并渲染出以下输出。
Conditionals and Loops in Template
Jinja2 模板语言允许在 HTML 脚本中包含条件语句和循环构造。Jinja2 用于这些编程元素的语法如下所示 −
Loop
{% for var in iterable %}
HTML
{% endfor %}
不难看出,Jinja2 语法与 Python 的 if 和 for 语句非常相似。不过,Jinja2 不使用缩进来标记块。相反,对于每个 if 都必须有一个 endif 语句。类似地,对于每个 for 语句,都必须有一个 endfor 语句。
Example
以下示例演示了模板条件和循环语句的使用。首先,Pyramid 代码使用一个 students 作为词典对象的列表,每个词典包含一个学生的 ID、姓名和百分比。此列表对象作为上下文传递给 marklist.html 模板
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.view import view_config
students = [
{"id": 1, "name": "Ravi", "percent": 75},
{"id": 2, "name": "Mona", "percent": 80},
{"id": 3, "name": "Mathews", "percent": 45},
]
@view_config(route_name='index', renderer='templates/marklist.html')
def index(request):
return {'students':students}
if __name__ == '__main__':
with Configurator() as config:
config.include('pyramid_jinja2')
config.add_jinja2_renderer(".html")
config.add_route('index', '/')
config.scan()
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()
将此程序保存为 marklist.py。现在,必须将以下 HTML 脚本保存为 marklist.html。它遍历从视图函数接收的 students 列表对象,并将学生数据渲染为一个 HTML 表格。第四列使用 Jinja2 if 语句语法显示通过/失败结果。
<html>
<body>
<table border=1>
<thead>
<tr>
<th>Student ID</th> <th>Student Name</th>
<th>percentage</th>
<th>Result</th>
</tr>
</thead>
<tbody>
{% for Student in students %}
<tr>
<td>{{ Student.id }}</td>
<td>{{ Student.name }</td>
<td>{{ Student.percent }}</td>
<td>
{% if Student.percent>=50 %}
Pass
{% else %}
Fail
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>