做为 python web 开发领域的一员, flask 跟 Django 在很多地方用法以都是相似的, 比如 flask 的模板
模板就是服务器端的页面, 在模板中可以使用服务端的语法进行输出控制
1. 模板的工作原理
在视图函数中, 通过 render_template 方法返回一个页面, 然后通过 Jinja2 语法来进行渲染
简单来说, 就是把服务器端的 html 页面解释成用户看到的页面, 而视图函数是通过上下文对象来进行变量的传递
在项目开发中, 视图函数经常会把一些服务器处理完成的变量传递给前端页面进行渲染,
比如在下面的例子中, 由 render_template 返回 html 页面时, 携带一些变量数据给 Jinja2 语法进行渲染
- from flask import Flask, render_template
- app = Flask(__name__)
- app.debug = True
- @app.route('/')
- def hello_world():
- return 'Hello World!'
- @app.route('/detail')
- def detail():
- message = {
- 'name':'jack',
- 'text':'杰克'
- }
- return render_template('detail.html',info=message)
- if __name__ == '__main__':
- app.run(debug=True)
前端页面 detail.html 内容为:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>{{ info.name }} 详细信息 </h1>
- <div>
我的名字叫:{{ info.text }}
- </div>
- </body>
- </html>
启动项目, 浏览器打开
http://127.0.0.1:5000/detail
页面, 前端页面渲染后效果为:
那么此时, 如果后台返回给前端的变量为一段 html 代码, 返回给前端经过 Jinja2 语法渲染后, 效果会是怎么样的呢??
2.Jinja2 语法安全机制
修改 message 变量, 然后由 render_template 返回
- @app.route('/detail')
- def detail():
- message = {
- 'name':'jack',
- 'text':'<h2 > 杰克 </h2>'
- }
- return render_template('detail.html',info=message)
前端页面不变, 刷新浏览器, 效果如下
可以看到, 返回的变量中包含 html 代码, 但是 Jinja2 语法并没有对这一小段代码进行渲染, 而是直接显示了出来
实际上这是为了安全, 因为如果后台返回的 html 代码中包含恶意的 js 代码, 如果直接就渲染了, 会造成站点被攻击.
那如果我就是想渲染后台返回给前端的 HTML 代码, 那应该怎么办呢
在 flask 中, 如果确认后台返回给前端进行渲染的变量中包含的 HTML 代码是安全的, 则可以使用一些方法来对这段 HTML 代码也进行渲染
方法一: autoescape 关闭安全机制
这种方法与 Django 的模板语法相同
后台代码不变, 修改前端 detail.html 代码
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- {% autoescape false %}
- <h1>{{ info.name }} 详细信息 </h1>
- <div>
我的名字叫:{{ info.text }}
- </div>
- {% endautoescape %}
- </body>
- </html>
此时, 再次刷新页面, 查看效果
方法二, 调用 Jinja2 的 safe 过滤器
如果觉得第一种方法有点麻烦, 可以使用第二种方法
后台代码不变, 同样修改 detail.html 页面
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>{{ info.name }} 详细信息 </h1>
- <div>
我的名字叫:{{ info.text | safe }}
- </div>
- </body>
- </html>
此时, 再次刷新页面, 效果跟第一种方法一样
在 flask 中, Jinja2 语法提供了很多过滤器, 可以在下面的地址进行查找
http://jinja.pocoo.org/docs/dev/templates/
3. 自定义过滤器
在写文章或博客的时候, 很多时候都会用到 Markdown 语法
在 flask 的 Jinja2 语法中, 并没有标准的 Markdown 语法过滤器, 此时可以使用扩展来自定义 Markdown 语法过滤器
修改 flask 项目文件
- from flask import Flask, render_template
- app = Flask(__name__)
- app.debug = True
- @app.route('/')
- def hello_world():
- return 'Hello World!'
- @app.route('/detail')
- def detail():
- message = {
- 'name':'jack',
- 'text':'<h2 > 杰克 </h2>'
- }
- return render_template('detail.html',info=message,markdown='## Markdown 编辑器 < br>` 注释 `')
- @app.template_filter('md')
- def markdown_html(txt):
- from markdown import markdown
- return markdown(txt)
- if __name__ == '__main__':
- app.run(debug=True)
修改 detail.html 前端页面
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>{{ info.name }} 详细信息 </h1>
- <div>
我的名字叫:{{ info.text | safe }}
- {{ markdown | md | safe }}
- </div>
- </body>
- </html>
刷新浏览器, 查看效果
在实际开发中,
后台向模板中传递的不只有变量和 filter, 还可能会向前端传递一个方法
, 此时可以使用 flask 的上下文来实现
修改 flask 项目文件
- #-*- coding: utf-8 -*-
- from flask import Flask, render_template
- app = Flask(__name__)
- app.debug = True
- @app.route('/')
- def hello_world():
- return 'Hello World!'
- def read_md(filename):
- from functools import reduce
- with open(filename,encoding='utf-8') as md_file:
- content = reduce(lambda x,y:x + y, md_file.readlines())
- return content
- @app.context_processor
- def methods():
- return dict(read_md=read_md)
- @app.route('/detail')
- def detail():
- message = {
- 'name':'jack',
- 'text':'<h2 > 杰克 </h2>'
- }
- return render_template('detail.html',info=message,markdown='## Markdown')
- @app.template_filter('md')
- def markdown_html(txt):
- from markdown import markdown
- return markdown(txt)
- if __name__ == '__main__':
- app.run(debug=True)
如果想在 Jinja2 语法中调用后台定义的某个函数时, 比如在这个例子中, 前端页面中调用后台定义的 read_md 方法来处理某个 Markdown 格式的文件时, 可以使用
context_processor 上下文处理器
.
在项目中应用了 context_processor 时,
flask 会把 context_processor 装饰的方法注册到 Jinja2 模板语法中
来, 这样就可以在 Jinja2 语法中调用后台的方法了
用 context_processor 装饰的后台方法可以在前端所有的 Jinja2 语法中调用
修改前端页面
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>{{ info.name }} 详细信息 </h1>
- <div>
我的名字叫:{{ info.text | safe }}
- {{ markdown | md | safe }}
- {{ read_md('editor.md') |md| safe}}
- </div>
- </body>
- </html>
刷新浏览器, 查看效果
使用过滤器和 context_processor 配置一起使用时, 可以很灵活的进行页面的渲染
来源: https://www.cnblogs.com/renpingsheng/p/9038533.html