网站建设兼职劳务协议书,网站登录模版 下载,wordpress自动空行,网站开发目录结构在之前的文章中#xff0c;简单介绍了Python Web开发框架Flask#xff0c;知道了如何写个Hello World#xff0c;但是距离用Flask开发真正的项目#xff0c;还有段距离#xff0c;现在我们目标更靠近一些 —— 学习下Jinja2模板。
模板的作用
模板是用来做什么的呢…在之前的文章中简单介绍了Python Web开发框架Flask知道了如何写个Hello World但是距离用Flask开发真正的项目还有段距离现在我们目标更靠近一些 —— 学习下Jinja2模板。
模板的作用
模板是用来做什么的呢模板是用来更高效地生成相应时的Html文本的没有模板可以手写比如之前的hello world示例写段html代码: h1Hello world!/h1
对于简单的练习还行但对于规模大的动态化程度高的项目来说这样写就有些勉强了即不利于项目和产品化。那么模板有什么好处呢 能让展现逻辑和业务逻辑 展示逻辑即UI就是用来给用户看和操作的业务逻辑是业务规则比如什么条件可以注册什么权限能考到什么。模板将展现逻辑封装起来业务逻辑写在视图函数中。 能使项目更易维护 由于展现逻辑和业务逻辑的分离它们可以由不同的开发人员来维护不会有代码冲突的问题 使项目更加安全 在做交互式开发中有个原则: 永远不要相信用户的输入因为恶意用户可能通过输入来注入关于注入以后有机会可以单独聊聊而模板在一定程度上会防注入例如用户输入一点html代码作为输入默认情况下模板会将其替换为网络安全字符以防止恶意注入。 能提高开发效率 有了模板相当于一个展示逻辑的函数所以就可以被复用可以用在不同的视图函数中也可以用在不同的项目中 思考下上面提到的展现逻辑和业务逻辑为什么不直接说成前台和后台呢? 如果你有答案和想法欢迎留言讨论。 Jinja2模板引擎
Jinja2是Flask框架默认支持的模板引擎并不是唯一也不是最好因人而异没有最好模板引擎不同的Web框架比如Django、Nodejs等都有自己的模板引擎甚至一些程序员自己实现的模板引擎我就这么干过但大体思路是一样的都是要将数据替换或者转换到用特殊格式标记了位置的模板中以合成动态的html这种技术不新鲜在之前的打印模板如水晶报表里就有无非就是标记和语法不同而已所以要举一反三。
引入渲染函数
像其他功能一样要使用模板引擎先引入 from flask import render_template 注意要将将模板文件放置在项目根目录(即 print(__file__)显示的路径)下的 templates文件夹中 例如模板文件 hello.html为 h1Hello {{ name }} /h1
视图函数可以写成: app.route(/user/name) def index(name): return render_template(hello.html, namename)
Flask提供的 render_template函数把Jinja2模板引擎集成到了程序中。render_template函数第一个参数是模板的文件名随后的参数都是键值对表示模板中变量的对应的真实值在上面代码中模板会接收到一个名为 name的变量
变量
模板文件就是普通的文本文件然后将需要替换的部分用双大括号( {{}})标记出来双大括号中表示要替换的变量名这个变量支持基本数据类型以及列表、词典、对象和元组。如模板 template.html: p A value form a string: {{ name }}./p p A value form a int: {{ myindex }}./p p A value form a list: {{ mylist[3]] }}./p p A value form a list, with a variable index: {{ mylist[myindex] }}./p p A value form a dictionary: {{ mydict[key] }}./p p A value form a tuple: {{ mytuple }}./p p A value form a tuple by index: {{ mytuple[myindex] }}./p
视图函数代码: app.route(/template/) def template(): name Jinja2 模板引擎 myindex 1 mylist [1,2,3,4] mydict { key: age, value: 25 } mytuple (1,2,3,4) return render_template(template.html, namename, myindexmyindex, mylistmylist, mydictmydict, mytuplemytuple)
显示结果: 过滤器
有些时候需要对要在模板中替换的值做一些特殊处理比如首字母大写去掉前后空格等等有种选择就是使用过滤器。
说明
Jinjia2模板引擎中过滤器类似于Linux命令中的管道,例如将字符串变量的首字母大写 h1{{ name | capitalize}}/h1
过滤器可以拼接和linux的管道命令一样如对值进行全部变大写并且去除前后空白字符 h1{{ name | upper | trim }}/h1
如上代码过滤器和变量之间用管道符号 | 相连相当于对变量值作进一步加工。
一些常用的过滤器
过滤器说明safe渲染是不转义capitalize首字母大写lower所有字母小写upper所有字母大写title值中每个单词首字母大写trim删除首位空白字符striptags渲染时删除掉值中所有HTML标签
注意safe过滤器默认情况下处于安全考虑Jinja2会转义所有变量例如一个变量的值为 h1Hello/h1, Jinja2会将其渲染成 lt;h1gt;Hellolt;/gt;,浏览器会显示出原本的值但是不会解释。如果需要浏览器解释的话可以使用 safe 过滤器 例如模板文件 html.html为: h1{{ html | safe }}/h1
视图函数为 app.route(/html) def html(): return render_template(html.html, htmlbbob/b) 注意千万别在不可信的值上使用 safe 过滤器例如用户在表单上输入的文本。 还有一些有用的过滤器 default可以当变量未定义时提供默认值如果想将 false、 False和空( none)视为未定义需要提供第二个参数为 true{% raw %} 当变量 name的未定义时上下两个显示效果一样当值为 none时上面会显示 Hellonone!, 而下面的会显示 Helloworld! !-- 提供默认值过滤器 -- h1Hello {{ name | default(world) }}!/h1 !-- 将false、False和空(none)视为未定义的默认值过滤器 -- h1Hello {{ name | default(world, true)! }}/h1 列表过滤器 min, max, 得到列表中的最小值或最大值
自定义过滤器
过滤器虽然有很多但总有不满足需求的时候例如首行文字缩进、将金额转化为中文的大写等等。过滤器实质就是个函数所以第一定义一个过滤器函数第二注册到Jinjia2的过滤器中。
#自定义过滤器函数
def mylen(arg):#实现一个可以求长度的函数return len(arg)
def interval(test_str, start, end):#返回字符串中指定区间的内容return test_str[int(start):int(end)]
#注册过滤器
env app.jinja_env
env.filters[mylen] mylen
env.filters[interval] intervalapp.route(/myfilter)
def myfilter():return render_template(myfilter.html, phone 135645xxx623)模板 h1电话号码是{{ phone }}, 长度为{{ phone | mylen }}运营商号{{ phone | interval(0,3) }}/h1 过滤器注册代码还可以写在初始化代码 __init__.py 中 控制结构
很多时候需要更智能的模板渲染即能给渲染编程比如男生一个样式女生一样样式控制结构指令需要用指令标记来指定下面介绍下一些简单的控制结构
条件
即在模板中用 if-else控制结构 {% if gendermale %} Hello, Mr {{ name }} {% else %} Hello, Ms {{ name }} {% endif %} 视图函数 app.route(/hello2/name/gender) def hello2(name, gender): return render_template(hello2.html, namename, gendergender) 在控制结构里代码语法同 python
循环
循环对于渲染列表很有帮助循环的标记是 for。例如奖列表的内容显示在 ul中 ul {% for name in names %} li{{ name }} /li {% endfor %} /ul 例如给定一个学生列表将其用无序列表 ul显示出来
宏——模板中的函数
模板中可以定义宏相当于定义了一个函数可以重复使用让逻辑更清晰。首先定义一个宏: {% macro render_name(name) %} li{{ name }}/li {% endmacro %} {% endraw %} 然后使用宏, 例如将循环结构的例子中显示名称的地方改为调用宏 {% raw %} ul {% for name in names %} {{ render_name(name) }} {% endfor %} /ul 调用宏和调用函数是一样的不过要将代码写在 {{}}双大括号内。一般我们会将宏存在单独的文件中以便复用在需要用到宏的地方引用就好了 {% import mymarco.html as macros %} ul {% for name in names %} {{ macros.render_name(name) }} {% endfor%} /ul 如上所述用improt引入宏定义文件通过as指定别名和python的模块引入一样。指定别名是一个良好的编程习惯可以将一个复杂的东西形象化同时像一个命名空间一样有效的避免冲突。
include
另外可以将多个模板片段写入一个单独文件再包含( include)在所有模板中以提高开发效率: {% include common.html %}
include进来的文件相当于将文件中的内容复制到 include的位置所以自使用之前需要考虑仔细
模板继承
如果觉得 include过于呆板灵活性差Jinja2模板引擎还有更高级的功能——继承。类似于Python代码中类的继承一起看看。首先定义一个基类, base.html:
!DOCTYPE html
html langen
headmeta charsetUTF-8{% block head %}title{% block title %}{% endblock %} - My Application/title{% endblock %}
/head
body{% block body %}h3这是基类的内容/h3{% endblock %}
/body
/html
其中的 block标签定义了可以被子类重构替换的部分每个 blcok标签需要指定一个特殊的名称例如 head、 title等以便子类用特定的名称来重构。另外 block标签需要有结束标签 endblock,类似于类C语言中的大括号当然 block标签也可以嵌套。接下来定义一个子类模板 hello3.html
!DOCTYPE html
html langen
{% extends base.html %}
{% block title %}Index{% endblock %}
{% block head %}{{ super()}}style/style
{% endblock %}
{% block body %}{{ super()}}h4这是子类的内容Hello world/h4
{% endblock %}
/html
app.route(/hello3)
def hello3():return render_template(hello3.html) 效果如图所示: 通过 extends标记来指定需要继承的基类然后用 block标记来设置子类需要替换调基类中的内容只要 block指定的名称一样就行。另外如不需要完全替换调基类的内容可以在子类 block中调用 super方法以获取基类在此名称下的内容这样就能达到更号的灵活性。
总结
今天介绍了Jinja2模板引擎的基本用法和特点期望通过不同的特点让你了解到模板的基本用法以便更快的使用和进一步学习更深入的内容。另外想通过Jinja2模板引擎说明模板的基本特征以便触类旁通、举一反三更快的学习其他优秀的模板, 同时也想说明模板不仅仅可以用在Web的开发中还可以用在自动化编码、测试等众多领域。