文 / 秦未
1.jinja2解析
今天学习Flask的模板引擎 -- jinja2,我们先看看它工作的原理:
说明:视图函数通过上下文与模板之间传递数据,模板由jinja2引擎驱动支持并生成HTML文件,这样展示在客户端浏览器中的内容就是完整的页面了。
我们之前有一个范例:
@app.route('/about')
def about():
return '<h1>about</h1>'
我们改变一下:
@app.route('/about')
def about():
return render_template('blog/about.html', **{
'text': 'Hello, World',
})
其中about.html内容 :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>关于页面</title>
</head>
<body>
{{ text }}
</body>
</html>
运行输出:
其中我们发现h1并没有生效,而是作为字符串完整的显示了出来,其实这是jinja2的自动转义功能在起作用,主要目的是防止跨站脚本攻击。
但如果我们能保证内容是安全的,我们想要实现标签的作用该怎么办呢?
jinja2提供两种办法禁用自动转义功能。
1.块元素包裹内容:
{#/app/templates/blog/about.html#}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>关于页面</title>
</head>
<body>
{% autoescape false%}
{{ text }}
{% endautoescape %}
</body>
</html>
说明:在{% autoescape false%}{% endautoescape %}内包裹的所有内容都会被禁止自动转义。
2.单独的
{#/app/templates/blog/about.html#}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>关于页面</title>
</head>
<body>
{{ text|safe }}
</body>
</html>
说明:在指定值后面加 “|safe”,即可在这个值中禁用自动转义。
最后效果是一样的:
第二种方法其实是模板引擎的过滤器,本质来说这是一种值的预处理方法(函数),每一个过滤器代表一个方法(函数),它接收|之前的参数,然后输出内容在当前位置,在模板中一个变量可同时使用多个过滤器,解析从左往右。
jinja2本身提供了相当多的过滤器,正常情况下足够我们使用了,当然我们也可以自定义过滤器。
2.自定义过滤器示例:
我们需要一个markdown过滤器,官方并没有提供。
首先下载一个mistune模块,这个markdown解析库是Python中最快的,据称比Markdown模块快10倍左右。
pip install mistune
然后在app.py 内增加一个装饰器加函数:
# /app/app.py
@app.template_filter('md')
def markdown_to_html(text):
import mistune
markdown = mistune.Markdown()
return markdown(text)
同时为了验证,修改about函数:
# /app/app.py
@app.route('/about')
def about():
return render_template('blog/about.html', **{
'text': '<h1>Hello, World</h1>',
'body': '## 演示'
})
about.html也要修改:
{#/app/templates/blog/about.html#}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>关于页面</title>
</head>
<body>
{{ text|safe }}
{{ body|md|safe }}
</body>
</html>
运行效果:
有时候,我们想在前台运行一个函数怎么办?
比如我们想实现一个功能:定义一个函数读取目录下的md文件并输出到前台。
先看源码:
# /app/app.py
def read_md(filename):
from functools import reduce
# 获取当前路径
basepath = path.abspath(path.dirname(__file__))
# 将路径连接
upload_path = path.join(basepath, filename)
with open(upload_path, encoding='UTF-8') as md_file:
# reduce为归纳的意思,主要作用是让获取的每一行都加上前一行。
content = reduce(lambda x, y: x + y, md_file.readlines())
return content
# 将read_md函数传递到前台
@app.context_processor
def inject_methods():
return dict(read_md=read_md)
先建立一个在app目录下的名叫md.md的文件:
![每日壁纸.jpg](http://upload-images.jianshu.io/upload_images/3980526-b9539b5712fcccee.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
## 1.jinja2解析
今天学习Flask的模板引擎 -- jinja2,我们先看看它工作的原理:
使用:
{#/app/templates/blog/about.html#}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>关于页面</title>
</head>
<body>
{{ text|safe }}
{{ body|md|safe }}
{{ read_md('md.md')|md|safe }}
</body>
</html>
{{ read_md('md.md')|md|safe }}这段代码从左往右执行,先执行这个函数read_md('md.md'),再将获取的内容转换为HTML,同时这个内容不需要转义。
运行效果:
---end---