13.模板
模板语言简称为DTL(Django Template Language)
13.1 模板语言
13.1.1 模板变量及解析顺序
模板变量名由数字,字母,下划线和点组成,不能以下划线开头,使用模板变量:
{{ 模板变量名 }}
解析顺序:
例如: {{ book.btitle }}
1)首先把 book 当成一个字典,把 btitle 当成键名,进行取值 book['btitle’]
2)把book当成一个对象,把 btitle当成属性,进行取值book.btitle
3)把book 当成一个对象,把 btitle 当成对象的方法,进行取值book.btitle
例如: {{ book.0 }}
1)首先把book当成一个字典,把0当成键名,进行取值book[0]
2)把book当成一个列表,把0当成下标,进行取值 book[0]
如果解析失败,则产生内容时用空字符串填充模板变量。
使用模板变量时,“. ”前面的可能是一个字典,可能是一个对象,也可能是一个列表。
·
13.1.2 模板标签
格式:{% 代码段 %}
for 循环:
{% for i in 列表 %}
xxx // 列表不为空时执行
{% empty %}
xxx // 列表为空时执行
{% endfor %}
可以通过{{ forloop.counter }}得到for循环遍历到了第几次。
if语句:
{% if条件 %}
{% elif条件 %}
{% else %}
{% endif %}
关系比较操作符:> , < , >= , == , !=
注:进行比较操作时,比较操作符两边必须有空格。
逻辑运算: not and or
代码实例:
book.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板标签</title>
<style>
.yellow {
background-color: yellow;
}
</style>
</head>
<body>
{% for i in books %}
{% if i.id <= 1 %}
<li class="yellow">{{ i.btitle }}</li>
{% endif %}
{% endfor %}
</body>
</html>
views.py
def books_play(request):
book_all = Book.objects.all()
return render(request, 'booktest/book.html', {'books': book_all})
实验结果:
·
13.1.3 模板过滤器
过滤器用于对模板变量进行操作
过滤器本质是python函数
date:改变日期的显示格式
length:求长度。字符串,列表,元组,字典长度
default:设置模板变量的默认值
格式:模板变量 | 过滤器: 参数
·
代码实例:
books_display.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>显示图书信息</title>
</head>
<h3>图书信息:</h3>
<a href="/create">新增</a>
<body>
{% for book in books %}
<li><a href="/books/{{ book.id }}">{{ book.btitle }}</a>---{{ book.bpub_date|date:'Y年-m月-d日' }} // 对日期的显示增加过滤器
<a href="/delete/{{ book.id }}">删除</a></li>
{% endfor %}
<br/>
default过滤器:<br/>
{{ content|default:'默认值' }}
</body>
</html>
views.py
def books_display(request):
books = BookInfo.objects.all()
return render(request, 'booktest/books_display.html', {'books': books})
实验结果:
·
自定义过滤器
1)首先,在app路径下创建 templatetags
2)在templatetags目录中创建自定义的python文件
3)导入包(from django.template import Library
)
4)创建LIbrary()对象
5)创建功能函数并进行装饰器装饰
6)在模板文件中加载自定义的python文件
7)增加过滤器
注:自定义的过滤器函数,至少有一个参数,最多两个参数
代码实例:
booktest/templatetags/filter_test.py
# 自定义过滤器
# 过滤器实质上是python函数
from django.template import Library
# 创建一个Library类的对象
register = Library()
@register.filter
def mod(num):
'''判断num是否为偶数'''
return num % 2 == 0
# 自定义的过滤器函数,至少有一个参数,最多两个
@register.filter()
def mod_val(num, val):
'''判断num是否能被val整除'''
return num % val == 0
books_display.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
{% load filter_test %}
<head>
<meta charset="UTF-8">
<title>显示图书信息</title>
</head>
<h3>图书信息:</h3>
<a href="/create">新增</a>
<body>
{% for book in books %}
<li>{{ book.id }}--{{ book.id|mod }}---<a href="/books/{{ book.id }}">{{ book.btitle }}</a>
---{{ book.bpub_date|date:'Y年-m月-d日' }}--{{ book.id|mod_val:3 }}
<a href="/delete/{{ book.id }}">删除</a></li>
{% endfor %}
<br/>
default过滤器:<br/>
{{ content|default:'默认值' }}
</body>
</html>
实验结果:
·
13.1.4模板注释
单行注释:
{# 注释内容 #}
多行注释:
{% comment %}
注释内容
{% endcomment %}
● 模板注释与html注释的区别
模板注释 通过浏览器检查网页源代码不会显示
html注释 通过浏览器检查网页源代码会显示出来
·
13.1.5 模板继承
在子模版中需要继承父模板时
{% extends '父模板路径' %}
● 子模版继承父模板后会继承父模板所有模板内容,并且无法直接增加内容,标题也和父模板一样
● 在父模板中增加预留块,在子模版中可通过对预留块的改写增加内容
● 在子模版的预留块中可通过 {{ block.super }}
继承父模板中该预留块的内容
● 对父模板的标题增加预留块,在子模版可以通过该预留块改写子模版的标题
·
实例代码:
parentTemplate.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}父模板{% endblock title %}</title>
</head>
<body>
<h1>这是父模板</h1>
{% block b1 %}
<h3>父模块b1信息</h3>
{% endblock b1 %}
{% block b2 %}
{% endblock b2 %}
</body>
</html>
subTemplate.html
{% extends 'booktest/parentTemplate.html' %}
{% block title %}子模版{% endblock title %}
{% block b1 %}
{{ block.super }}
<h3>这是子模块b1的内容</h3>
{% endblock b1 %}
{% block b2 %}
<h3>这是子模块b2的内容</h3>
{% endblock b2 %}
实验结果:
·
13.1.6 html转义
在模板上下文中的html标签默认是会被转义的
小于号 < 转换为 <
大于号 > 转换为 >
单引号 ‘ 转换为 '
双引号 " 转换为 "
与符号 & 转换为 &
要关闭模板上下文的转义,有两种方法:
● 过滤器
{{ 模板变量|safe }}
● 模板标签
{% autoescape off %}
模板语言代码
{% endautoescape %}
代码实例:
views.py
def escape_test(request):
return render(request, 'booktest/escape_test.html', {'content': '<h1>hello</h1>'})
escape_test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>转义</title>
</head>
<body>
未进行转义时:<br/>
{{ content }}
<br/>
<br/>
用过滤器进行转义:
{{ content| safe }}
<br/>
用模板标签进行转义:
{% autoescape off %}
{{ content }}
{{ content }}
{% endautoescape %}
</body>
</html>
实验结果:
● 在模板硬编码中的字符串默认不会经过转义,如果需要转义,则需要手动进行转义
硬编码指的是在模板文件中固定死的静态代码
代码实例:
escape_test.html
模板硬编码中的字符串默认不会经过转义:<br/>
{{ tag|default:'<h1>hello</h1>' }}<br/>
<br/>
手动进行转义:<br/>
{{ tag|default:'<h1">>hello</h1>' }}
</body>
</html>
实验结果:
·
·
13.2 模板目录(templates)有两种创建路径:
1)在项目根目录中创建templates
目录,该目录下存放模板文件
创建好后,在setting.py 文件中,配置一下模板文件的目录
在setting.py
文件中有一个变量 BASE_DIR 表示这个项目的绝对路径,在本实验环境下为“/home/user/桌面/python/Django_test/test1
”
则在模板路径中应该填入
os.path.join(BASE_DIR, ‘templates’) (路径相加需要用到os.path.join()方法)
2)在应用目录下创建templates
目录,该目录下存放模板文件
在应用目录下创建后无需填写setting.py
文件中的TEMPLATES的‘DIRS’
,但必须让‘APP_DIRS'
设置为True
注:当两种模板目录的存放方式都写了时,Django框架寻找模板文件时优先在项目根目录下寻找templates目录,如果没找到再去应用目录下寻找templates目录,当都没找到的话就会报出错误
TemplateDoesNotExist at xxx/xxx
·
13.3 模板文件加载顺序
当服务器url正确时,服务器寻找相应的模板文件的顺序为下面红框中内容
·
·
在templates目录下创建与应用同名的目录,比如这里我的应用名是booktest,我就在templates目录下创建一个booktest目录,在每个应用目录下存放属于该应用的模板文件
·
通过render
方法调用模板文件,获取内容,进行模板渲染(将传入的值替换模板文件中相应的值),最后返回给浏览器