- 模板层
Django中的HTML文件并不是一个简单的前端页面,他支持多种渲染方式;
比如 Smart 或是 Jinja 这样出名的模板语言引擎,默认django使用的是templates引擎来进行模板页面的渲染,这也被称为Django模板语言(DTL)
-
-
- 模板语言主要有模板变量和模板标签
-
<div> {{ account }} </div>
-
-
- 模板变量通过视图函数传递字典变量,字典的 key 值为对应模板变量名,对应 value 是模板变量实际被渲染的值
-
def index(request): content = {'account':'test'} return render(request,html,content)
-
-
- 最终渲染结果
-
<div> test </div>
模板引擎遇到这个变量,将会计算他,并且将结果覆盖;如果视图函数中,并没有给这个模板变量赋值,也没有关系,模板会自动将这个 {{ account }} 处理为一个空
注意:模板变量名,只能以字母数字下划线构成,下划线不可以打头,并且也不可以使用表单符号组成模板。
-
- 变量获取方式
当我们返回的是一个字符串数据,这应该是最简单的处理方式,前端模板会直接将它展示到页面中。
如果返回的是一个列表序列数据或者字典键值对数据,我们可以使用模板语言中的 . 符号来进行其中值的获取,当模板变量中有符号 . 的存在时,比如 content.key 他会按照如下顺序来进行查找。
1.字典查找: content[key]
2.对应属性和方法查找: content.key
¤ 注意:因为对应key值的查找优先级要低于属性方法,所以要尽量避免使用数据内置方法作为key值。
3.序列索引方式查找: content[index]
-
- Python数据在模板
Python常用数据有int,float,str,list,tuple,dict,set等,把他们都通过模板变量传递到模板页面试试。
def index(request): int_ = 123 float_ = 0.123 str_ = 'str' list_ = ['l','i','s','t'] tuple_ = ('t','u','p','l','e') dict_ = {"key":"value"} set_ = {'s','e','t'} return render(request,"index.html",locals())
locals() :该函数将当前作用域下的所有变量名和对应变量值组成字典,免去了我们构造存储字典的麻烦。
<p>{{ int_ }}</p> <p>{{ float_ }}</p> <p>{{ str_ }}</p> <p>{{ list_ }}</p> <p>{{ tuple_ }}</p> <p>{{ dict_ }}</p> <p>{{ dict_.key }}</p> <p>{{ set_ }}</p>
到了模板页面上,这些变量值其实也都像变成了字符串一样,直接展示
123 0.123 str ['l', 'i', 's', 't'] ('t', 'u', 'p', 'l', 'e') {'key': 'value'} {'e', 's', 't'}
-
- for标签
使用模板中使用标签语言 {% for %} 和 {% endfor%} ,对视图函数传递的数据集进行遍历访问,比如上面传递的字符串,列表,元祖,字典,集合这样的数据
和普通模板变量不同,模板标签使用大括号百分号的组合 {% lag %} ,具有有一些特殊的功能性
模板中的标签 {% for %} 与Python中的for循环类似,要记得有闭合模板标签 {{ endfor }}
{% for var in sequence %} {{ var }} {% endfor %}
来把上面的数据进行访问
{% for var in str_ %} <p>{{ var }}</p> {% endfor %} --------------------- {% for var in list_ %} <p>{{ var }}</p> {% endfor %} --------------------- {% for var in tuple_ %} <p>{{ var }}</p> {% endfor %} --------------------- {% for var in set_ %} <p>{{ var }}</p> {% endfor %}
看到的效果和在Python中迭代访问的结果是差不多的,并且模板循环还会使对应的标签也进行循环
接下来来看字典,通过模板循环从字典中取出来的是字典的key值
{% for var in dict_ %} <p>{{ var }} {{ dict_.var}}</p> {% endfor %}
在for循环遍历访问字典的时候,不能再像Python语法里一样,直接通过迭代获取 key 之后通过dict[key] 或是 dict.key ,拿到对应value;
模板变量不会把 var 解释成取到的对应 key 值,var只是作为了一个单纯的 var 字符串,除非在字典中,有var 字符串做为字典的键值,否则是取不到的
正确的对字典中键值对进行获取的方式是通过内置字典 items 属性:
{% for key,value in dict_.items %} <p>{{ key }} {{ value}}</p> {% endfor %}
注意:模板语言中,不会出现索引超出范围的 IndexError 或者Key值不存在的 KeyError ,取不出任何东西则只是一个空.
在 {% for %} 循环中,我们还可以使用很多有用的模板变量,方便我们控制循环:
{% for var in iterable %} {{ forloop.counter }} <!--当前循环次数,从1开始计数 --> {{ forloop.counter0 }} <!--当前循环次数,从0开始计数 --> {{ forloop.revcounter }} <!--当前循环次数,从最大长度开始 --> {{ forloop.revcounter0 }} <!--当前循环次数,从最大索引开始 --> {{ forloop.first }} <!-- 判断是否为第一次循环 --> {{ forloop.last }} <!-- 判断是否为第一次循环 --> {{ forloop.parentloop }} <!-- 当循环嵌套时,访问上层循环 --> {% endfor %}
通过 {% empty %} 标签判断迭代对象是否为空:
{% for var in test_list %} {{ var }} {% empty %} 空空如也 {% endfor %}
-
- if标签
可以通过 {% if %} 标签语法来进行模板变量的值判断;
语法如下:
{% if test_list %} 列表不为空 {% elif test_dict %} 列表为空,字典不为空 {% else %} 列表字典均为空 {% endif %}
并且 if 标签还支持 and 、 or 及 not 来进行变量的布尔判断:
{% if test_list and test_dict %} 列表、字典均不为空 {% endif %}
{% if not test_list %} 列表为空时才能满足IF条件判断 {% endif %}
{% if test_list or test_dict %} 列表、字典某一个不为空 {% endif %}
{% if not test_list or test_dict %} 列表为空或字典不为空 {% endif %}
{% if test_list and not test_dict %} 列表不为空并且字典为空 {% endif %}
也支持同时使用and及or语句,但是and的条件判断优先级要高于or语句:
{% if a or b and c %} 等同于 {% if a or (b and c) %}
if 标签还支持 == 、 != 、 > 、 < 、 >= 、 <= 的判断用法:
{% if var == "1" %} 这个值是"1" {% endif %}
{% if var != "x" %} 判断不相等成立 {% endif %}
{% if var < 100 %} var大于100 {% endif %}
{% if var >= 100 %} var大于100 {% endif %}
如果判断的数据类型在后台传递到模板变量时具体数值类型为整型或浮点型而不是字符串,不需要在判断的时候加字符串的标识引号。在模板语言中,不支持连续判断:
{% if 100 > var > 50 %} var大于50小于100 {% endif %}
应该使用and语句写成这样:
{% if 100 > var and var > 50 %} var大于50小于100 {% endif %}
除去运算符之外, if 标签还支持 in 和 not in 的判断运算:
{% if 1 in test_list %} 列表中有数字1 {% endif %}
- 其他常用标签
其实 django 官方提供了不只 if 和 for 这样的模板标签,还提供了很多可以让我们在模板页面上实现之前只能在后台进行逻辑实现的功能标签,比如以下:
-
- comment 标签
comment 标签常用来注释,在 {% comment %} 和 {% endcomment %} 中间的部分内容会被忽略;
这个标签不能嵌套使用。
{% comment %}
这里的内容会被忽略,相当于注释起来。
{% endcomment %}
-
- autoescape 标签
默认情况下,为了安全起见,模板在接收到一个 HTML 标签或者 css 样式等具有实际意义的变量字符串时;会对他进行转义,不会将这个字符串处理为HTML中实际的标签。一个 <h1> 标签到最后会被处理成:
<h1> ,这样浏览器就不会把他解释成一个标签的样式了
-
-
- 转义规则
-
符号 | 转义规则 |
< | %lt; |
> | > |
'(单引号) | ' |
"(双引号) | " |
& | & |
那么有的时候,我们可能需要这样类似的HTML标签真正效果展示出来,
比如一个 <h1> 标签我们希望他真正展示出 h1 的样子,而不是一个朴素的 <h1> 字符串,那么就需要我们使用autoescape标签来进行防止转义处理
str_ = "<h1>这是H1标签</h1>"
{% autoescape on %} {{ str_ }} {% endautoescape %} {% autoescape off %} {{ str_ }} {% endautoescape %}
-
- cycle 标签
cycle 标签提供一些可迭代数据;
它的结构像是一个环,其中的数据通过空格分割,你可以使用任意数量的值,作为接下里每一次循环迭代的数据。
其他包含在单引号 ' 或者双引号 " 中的值被认为是可迭代字符串,如果没有被字符串引号包围的值被当作模版变量
list_ = ['l','i','s','t'] # 视图定义的模板变量
<style> .red{ color:red; } .blue{ color:blue; } </style> {% for var in list_ %} <p class="{% cycle 'red' 'blue' %}"> {{ var }} </p> {% endfor %}
很简单的就可以通过 cycle 标签进行循环中的样式切换啦
循环遍历出来的列表中每一个字都是换着颜色展示
某些时候,我们可能希望在使用一次 cycle 之后,接下来使用不是继续向后迭代取值,而是继续沿用这一次取到的值;
那么我们可以通过 as 语法给 cycle 标签取别名,在接下来需要沿用的地方直接使用别名作为模板变量即可,比如这样:
{% for var in list_ %} <p> {% cycle 'red' 'blue' as style %} </p> <span>{{ style }}</span> <span>{{ style }}</span> {% endfor %}
每一次循环取到的cycle其中的值,都可以通过别名style在这次循环区域中重复利用而不递进
但是我们发现个问题, as 语句本身在使用时也会造成对 cycle 中的数据进行一次取值,那有什么办法可以在第一次 as 语句出现时,我只做声明,而不是为了取值, django 模板中提供了一个叫 silent 的属性,可以用
来 as 命名时不进行取值动作
{% cycle 'red' 'blue' as style silent %}
{% cycle 'red' 'blue' as style silent %} <h1>{{ style }}</h1> <h1>{{ style }}</h1> {% cycle style %} <h1>{{ style }}</h1> {% cycle style %} <h1>{{ style }}</h1> <h1>{{ style }}</h1>
通过 silent 可以在初次定义时不进行取值,
接下来使用 cycle 所创建的迭代器,每次访问得到当前值,不会继续向后迭代;
如果希望取到下一个值,可以使用迭代器标签 {% style %} ,这次访问不会生产数据,但是会让迭代访问位置向后推进一次,在接下来 {{ style }} 使用将得到下一个值
red
red
blue
red
red
-
- ifchanged 标签
ifchanged 标签用在 for 标签中;
检测这一次迭代的值和上一次迭代的值是否有改变,可以搭配 else 标签使用,用来确定是没有改变;
检查标签 {% ifchanged %} 和 {% endifchanged %} 之间的数据在每一次迭代过程中是否发生改变
list_ = [1,1,1,2,3]
{% for var in list_ %} {% ifchanged %} {{ var }} {% else %} 数据未发生变化 {% endifchanged %} <br> {% endfor %}
1
数据未发生变化
数据未发生变化
2
3
-
- firstof标签
firstof 标签用来查找到标签内变量中第一个为 True 的参数并输出,如果标签内变量均为 False ,那么输出空
{% firstof 0 0 0 0 0 "哈哈哈" %}
哈哈哈
-
- ifequal 标签
ifequal 标签接收两个变量,用来判断这两个值是否相等,如果相等,展示对应
{% ifequal 1 "1" %} <h3>两个值相等</h3> {% else %} <h3>两个值不等</h3> {% endifequal %} <br>
都不用想的,俩类型都不一样
-
- ifnotequal 标签
上面的反义
-
- now 标签
显示日期或时间,标签必须一个参数,用来指定当前时间日期的描述方式;
输出最终格式与项目时区及语言设置有关
参数是一个描述字符串,比较多,记着常用的就行
秒 | |
u | 微秒,000000-9999 |
s | 秒,00-59 |
Z | 时区偏移量(UTC),单位为秒。-43200到43200 |
U | 自Unix 时间以来的秒数。1970年1月1日00:00:00 UTC |
分钟 | |
i | 分钟,00-59 |
小时 | |
g | 12小时格式,1-12' |
G | 24小时格式,00-23 |
h | 12小时格式,00-12 |
H | 24小时格式,00-23 |
O | 时区差值,单位小时,如:Asia/Shanghai时区:+0800 |
p | 当前几时几分,如:5:30 pm |
f | 当前几时几分,不包含上下午标示,如:5:30 |
a | 小写字母:a.m.、p.m |
A | 大写字母:AM、PM |
月份 | |
b | 月份英文字母的前三个表示,均小写。如:"aug" |
d | 这个月的第几天,01-31 |
j | 这个月的第几天,1-31 |
E | 当前时区月份英文单词全拼 |
F | 当前月份英文单词全拼 |
m | 第几月,01-12 |
M | 月份英文字母的前三个表示,首字母大写。如:"Aug" |
n | 第几月,1-12 |
N | 美联社月份缩写,如:'Jan.','Feb.','March','May' |
星期 | |
D | 星期几的英文单词前三个表示,首字母大写,如:'Fri' |
I | 星期几的英文单词全拼,如:'Friday' |
w | 星期几的数字,0(星期日)-6(星期六) |
W | ISO-8601周数,今年第几周 |
年 | |
L | Bool值判断是否为闰年 |
y | 第几年两位数字,如:2018年,返回18 |
Y | 第几年,目前是:2018 |
Z | 今天是今年的第几天 |
其他 | |
c | ISO 8601时间格式 |
e | 当前时区名称:CST(美国-6:00,澳大利亚+9:30,中国+8:00,古巴-4:00) |
r | RFC 5322格式化日期 |
S | 一个月的第几天的英文序数后缀:'st','nd','rd'或'th' |
t | 当前月份的天数:28-31 |
T | 当前时区 |
选出你想表达的时间,比如年前年月日,那么可以这样
字符串 | 对应格式 时间 |
DATE_FORMAT | 'N j, Y' Feb. 5, 2018 |
DATETIME_FORMAT | 'N j, Y, P' Feb. 4, 2013, 4 p.m. |
SHORT_DATE_FORMAT | 'm/d/Y' 12/31/2015 |
SHORT_DATETIME_FORMAT | 'm/d/Y P' 12/31/2019 11:59 p.m. |
<ul> <li>DATE_FORMAT: {% now "DATE_FORMAT" %}</li> <li>DATETIME_FORMAT: {% now "DATETIME_FORMAT" %}</li> <li>SHORT_DATE_FORMAT: {% now "SHORT_DATE_FORMAT" %}</li> <li>SHORT_DATETIME_FORMAT: {% now "SHORT_DATETIME_FORMAT" %}</li> </ul>
DATE_FORMAT: March 26, 2019 DATETIME_FORMAT: March 26, 2019, 3:45 a.m. SHORT_DATE_FORMAT: 03/26/2019 SHORT_DATETIME_FORMAT: 03/26/2019 3:45 a.m.
最后 now 标签也支持 as 的用法,可以方便我们在模板中使用一个已经格式化好的输出
{% now "Y-m-d H:i:s" as show_time %} <p>{{ show_time }}</p>
发现时间输出不正确,记得查看 settings 文件下的 TIME_ZONE 配置