笔记主要基于官方文档,从中提取要点和记录笔记,关键处包含了官方文档链接。详见官方文档。
官方文档:Django documentation
博客推荐:Django2.2教程
官方文档视图层:模板层
目录
1.模板简介
2.模版语言
2.1.模版变量
2.2. 模版标签(Tags)
2.3. 过滤器
2.3.1.过滤器介绍和内置过滤器
2.3.2. 编写自定义的模板过滤器
自定义模板过滤器
2.4. 模版注释(Comments)
3.模板继承
4.自动HTML转义
作为Web框架,Django提供了模板,用于编写html代码,还可以嵌入模板代码更快更方便的完成页面开发,再通过在视图中渲染模板,将生成最终的html字符串返回给客户端浏览器。模版致力于表达外观,而不是程序逻辑。模板的设计实现了业务逻辑view与显示内容template的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用。
总之,模板的功能就是产生html,控制页面上展示的内容。
关于模板的基本使用,参考:入门阶段的模板部分、模板概述(官方)
模板文件包含两部分内容:
- 静态内容:css、js、html
- 动态内容:用于动态去产生一些网页内容。通过模板语言来产生。
模板文件的使用
视图调用模板分为三步骤:
- 找到模板:即加载模版文件。比如去模版目录下面获取html文件的内容,得到一个模板对象。
- 用from django.template import loader、loader.get_template('模版路径')
- 定义模版上下文:向模板文件传递数据。
用from django.template import RequestContext, RequestContext() 函数(Django2.x实测失效,报错context must be a dict rather than RequestContext. 。原因是新的版本中,上下文应该是dict)- 更新:定义一个字典作为上下文,如空字典 {}
- 渲染模板:得到标准的html内容。
- 用template.render(context)
视图调用模板都要执行以上三部分,为了减少开发人员重复编写加载、渲染的代码,Django提供了一个快捷函数:
render()
,用于调用模板。方法render()
包含3个参数:
- 第一个参数为request对象
- 第二个参数为模板文件路径
- 第三个参数为字典,表示向模板中传递的上下文数据
Django处理模板分为两个阶段:
1. 加载:根据给定的路径找到模板文件,编译后放在内存中。
(具体的:首先去配置的模板目录下面去找模板文件。再去INSTALLED_APPS下面的每个应用的templates去找模板文件,前提是应用中必须有templates文件夹。)
2. 渲染:使用上下文数据对模板插值并返回生成的字符串。
官方文档:The Django template language、The Django template language概述
博客:https://www.liujiangblog.com/course/django/145
模板变量名是由数字,字母,下划线和点组成的,不能以下划线开头。点(".")也有可能会在变量名中出现,不过它有特殊的含义。变量名称中不能有空格或标点符号。
当模版引擎遇到一个变量,它将从上下文context中获取这个变量的值,然后用值替换掉它本身。
使用模板变量时,. 前面的可能是一个字典,可能是一个对象,还可能是一个列表。
当模板系统遇到一个点,它会尝试下面的动作去解析,顺序如下:
- 字典查询(Dictionary lookup)
- 属性或方法查询(Attribute or method lookup)
- 数字索引查询(Numeric index lookup)
如果解析失败,则产生内容时用空字符串填充模板变量。
例如:{ { book.btitle }}
- 首先把book当成一个字典,把btitle当成键名,进行取值book['btitle']
- 把book当成一个对象,把btitle当成属性,进行取值book.btitle
- 把book当成一个对象,把btitle当成对象的方法,进行取值book.btitle
标签看起来像是这样的: {% tag %}
。
有些标签在使用时需要有开始和结束标签 (像这样 {% tag %} ... 内容 ... {% endtag %}
).
Django内置了大约二十几个标签. 可以在 内置标签参考 阅读有关内置标签的内容。
一些常用的标签如下:
for标签语法如下:
{%for item in 列表%} 列表不为空时执行循环逻辑 { {forloop.counter}}表示当前是第几次循环,从1开始 {%empty%} 列表为空或不存在时执行此逻辑 {%endfor%}
可以通过{ { forloop.counter }}得到for循环遍历到了第几次。
if标签语法如下:
{%if ...%} 逻辑1 {%elif ...%} 逻辑2 {%else%} 逻辑3 {%endif%}
比较运算符如下:
注意:运算符左右两侧不能紧挨变量或常量,必须有空格。
== != < > <= >=
布尔运算符如下:
and or not
还可以创建自己的自定义模板过滤器,请参见 自定义模板(template)的标签(tags)和过滤器(filters).
过滤器用于对模板变量进行操作。通过管道符 (|
) 间隔变量和过滤器来使用过滤器。
语法格式:模板变量|过滤器:参数
过滤器参数包含空格的话,必须用引号包起来。例如,使用逗号和空格去连接一个列表中的元素,你需要使用{ { list|join:", " }}
。
Django提供了大约六十个内置的模版过滤器。You can read all about them in the built-in filter reference.。
一些常用的模版过滤器:
date:改变日期的显示格式。
- 表示年,格式为4位,y表示两位的年。
- m表示月,格式为01,02,12等。
- d表示日, 格式为01,02等。
- j表示日,格式为1,2等。
- H表示时,24进制,h表示12进制的时。
- i表示分,为0-59。
- s表示秒,为0-59。
{ {value|date:"Y年m月j日 H时i分s秒"}}
length:Returns the length of the value. 。包括字符串、列表、元组、字典等。
{ { value|length }}
如果
value
为['a', 'b', 'c', 'd']
, 那么输出为4
.
default:设置模板变量的默认值。
{ { value|default:"nothing" }}
如果
value
为false或者为空,那么他将显示为 "nothing
" .
filesizeformat:格式化为“人类可读”文件大小单位(即'13 KB',4.1 MB','102 bytes'等)。
{ { value|filesizeformat }}
如果value是123456789,输出将会是117.7MB。
可以创建自己的自定义模板过滤器,请参见 自定义模板(template)的标签(tags)和过滤器(filters).
Django为我们提供了自定义的机制,可以通过使用Python代码,自定义标签和过滤器来扩展模板引擎,通过 {% load %}
标签使其可用。可以说过滤器本质就是python中的函数,注册后就可以在模板中当作过滤器使用。
可以新开一个app用来自定义标签和过滤器,也可以在原有的某个app中添加。
(一)在app中新建一个templatetags
包(包名字固定),包和views.py、models.py等文件处于同一级别目录下。这是一个包!不要忘记创建__init__.py
文件以使得该目录可以作为Python的包。(注:重启服务器后,才能在模板中使用标签或过滤器。)
(二)在templatetags包新建一个模块(即在templatetags目录下创建py文件)
将自定义的标签和过滤器将放在templatetags包下的一个模块里。
这个模块的名字是后面载入标签时使用的标签名,所以要谨慎的选择名字以防与其他应用下的自定义标签和过滤器名字冲突,当然更不能与Django内置的冲突。(templatetags包中放多少个模块没有限制)
(三)在INSTALLED_APPS
中注册包含自定义标签/过滤器的app,让{% load xxx %}
标签在模板正常工作。 {% load %}
语句会加载指定名字的 Python 模块的 tags/filters,而非加载应用。
(四)要在模块内自定义tags/filters,这个模块必须包含一个名为register
的变量,它是template.Library
的一个实例,所有的 tags 和 filters 均在其中注册。所以,在模块的开始,输入以下内容:
from django import template
register = template.Library()
可以阅读Django的默认过滤器和标记的源代码作为参考。分别位于django/template/defaultfilters.py
和django/template/defaulttags.py
中。
或者,模板标签模块能通过 DjangoTemplates
的 'libraries'
参数注册。
具体的,在setting.py中,在TEMPLATES的'OPTIONS': {...}增加一项:
#...
'OPTIONS': {
#...
'libraries': {
'my_customer_tags': '你的应用名.templatetags.模块名',
}
},
#...
1. 编写过滤器
自定义过滤器本质就是一个带有一个或两个参数的Python函数。
注意:这个Python函数的第一个参数是你要过滤的对象,第二个参数才是你自定义的参数。而且最多总共只能有两个参数,所以你只能自定义一个参数!
- 变量的值:不一定是字符串形式。
- 参数的值:可以有一个初始值,或者完全不要这个参数。
例如,在
{ { var|foo:"bar" }}
中,foo过滤器应当传入变量var和参数"bar"。
以下是官方文档 过滤器定义的例子:
def cut(value, arg): """将value中的所有arg部分切除掉""" return value.replace(arg, '')
在模板中使用这个过滤器:
{ { somevariable|cut:"0" }}
大部分的过滤器并没有参数。这样的话,只需要把这些参数从函数中去掉就好。例子如下:
def lower(value): # Only one argument. """Converts a string into all lowercase""" return value.lower()
2.注册自定义过滤器
相关类:django.template.Library.filter()
写好过滤器定义后,用 Library
实例调用register
去注册它,方法是调用register.filter
register.filter('cut', cut)
register.filter('lower', lower)
Library.filter()
方法需要两个参数:
也能以装饰器的模式使用 register.filter()
:
@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')
@register.filter
def lower(value):
return value.lower()
若像第二个例子展示的一样不填 name 参数,Django 会将函数名当做过滤器名。
单行注释:
要注释掉行的一部分,在模板中使用注释语法: {# #}
注释可以包含任何模板代码, 使其生效或无效. 例如:
{# {% if foo %}bar{% else %} #}
多行注释:
{% comment %}
注释内容
{% endcomment %}
模板注释在网页源代码中不可见,HTML注释在网页源代码中可见。
HTML注释:
Django模板中最强大和最复杂的部分就是模板继承. 模板继承允许你建立一个基本的"骨架"模板, 它包含了你网站所有常见的元素,并定义了可以被子模板覆盖的 块(blocks) .
模板继承和类的继承含义是一样的,模板继承也是为了重用html页面内容。主要是为了提高代码重用,减轻开发人员的工作量。
典型应用:网站的头部、尾部信息。
父模板
如果发现在多个模板中某些内容相同,那就应该把这段内容定义到父模板中。通常被命名为base.html
标签 block
:用于在父模板中预留区域,留给子模板填充差异性的内容,名字不能相同。 为了更好的可读性,建议给endblock标签写上名字,这个名字与对应的block名字相同。父模板中也可以使用上下文中传递过来的数据。
{% block 块名 %}
块中间可以写内容,也可以不写(称为预留块)
{% endblock 块名%}
子模板
标签extends:继承,写在子模板文件的第一行。
继承格式:{% extends 父模板文件路径%}
子模版不用填充父模版中的所有预留区域。
填充父模板中指定名称的预留区域。
{% block 块名 %}
{ { block.super}} #用于获取父模板中block的内容
重写的内容
{% endblock 块名%}
通常
实例和更多内容见官方文档:模板继承
模板对上下文传递的字符串进行输出时,会对以下字符自动转义。
小于号< 转换为 <
大于号> 转换为 >
单引号' 转换为 '
双引号" 转换为 "
与符号& 转换为 &
关闭转义
过滤器escape可以实现对变量的html转义,默认模板就会转义,一般省略。
{ { 模板变量|escape}}
过滤器safe:禁用转义,告诉模板这个变量是安全的,可以解释执行。
{ { 模板变量|safe}}
也可以使用:autoescape标签接受on或者off作为它的参数。
自动转义标签autoescape还会作用于扩展(extend)了当前模板的模板,以及通过include标签包含的模板,就像所有block标签那样。
{% autoescape off %}
模板语言代码
{% endautoescape %}
模板硬编码(在模板中写死的内容)中的字符串默认不会经过转义,如果需要转义,那需要手动进行转义。
更多内容见官方文档。
-----end-----