一、模板介绍
Django的模板 = HTML代码 + 模板语法
存放在templates目录下的HTML文件就称为模板文件,如果我们想要返回 的HTML文件中的数据是动态的,那么就必须在HTML文件中嵌入变量,这就会用到Django的模板语法。
二、变量
在Django的模板语言中的变量语法:
View:{ ' HTML变量名 ' : ‘ views变量名 ’ }
HTML:{{ 变量名 }}
views.py 文件
from django.shortcuts import render
import time
def index(request):
times = time.time()
name = '小杨'
name_list = ['小杨', '艾伦', '鲍勃']
info_dict = {'name': '小杨', 'age': 18, 'job': '攻城狮'}
class A:
def __init__(self, hobby):
self.hobby = hobby
def func(self):
return self.hobby
# 也可以传入对象
Bob = A('攻城狮')
# 将数据传递给 index.html 文件进行渲染在发送给浏览器
return render(request, 'index.html', {'times': times, 'Bob': Bob, 'name': name, 'name_list': name_list, 'info_dict': info_dict})
index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 接收数据进行渲染 -->
<p>{{ times }}</p>
<p>{{ name }}</p>
<p>{{ name_list.2 }}</p> <!-- 取列表中索引为2的数据 -->
<p>{{ info_dict.age }}</p> <!-- 取字典中键值为age的数据 -->
<p>{{ Bob.func }}</p> <!-- 执行对象中的方法返回数据 -->
</body>
</html>
三、过滤器
过滤器类似于python的内置函数,用来把视图传入的变量加以修饰后在显示
过滤器的语法:{{ 变量名|过滤器 : 可选参数 }}
注意事项:
- 过滤器支持“ 链式 ” 操作 。
- 过滤器参数包含空格需要用引号包裹起来。
- '|' 左右没有空格
常用过滤器
default
如果一个变量是false或者是空,就使用给定的默认值。否则,使用变量的值。
{{ value|default:"默认值" }}
length
返回值的长度,主要用于字符串和列表。
{{ value|length }}
filesizeformat
将值的格式转换为一个可读的,主要用于显示文件大小
如果 value 是 123456789,输出将会是 117.7 MB。
{{ value|filesizeformat }}
slice
切片
{{ value|slice:"2:4" }}
date
格式化,若value = datetime.datetime.now()
{{ value|date:"Y-m-d H:i:s" }}
safe
转义,若value是一串代码,就可以对其进行转义成非代码的,防止xss攻击。
{{ value|safe }}
truncatechars
如果字符串的字符个数多于指定的字符数量,那么就会被截断。截断的字符串将以可翻译的序号(...)结尾
{{ value|truncatechars:'6' }} # 后面的三个省略号也算在6个字符里面
truncatewords
在一定数量的字后截断字符串,是截多少个单词。
{{ value|truncatewords:2 }}
cut
移除value中所有的与给出的变量相同的字符串
{{ value|cut:'移除的字符' }}
join
使用字符串连接列表。
{{ list|join:', ' }}
四、标签Tags
标签是为了在模板中完成一些特殊功能,语法为{% 标签名 %},一些标签还需要搭配结束标签 {% endtag %}
for 标签
1、遍历每一个元素
{% for food in foods_list %}
<p>{{ food }}</p>
{% endfor %}
2、可以利用{% for obj in list reversed %}反向循环。
{% for food in foods_list reversed %}
<p>{{ food }}</p>
{% endfor %}
3、遍历一个字典
{% for k, v in f_dict.items %}
<p>{{ k }}:{{ v }}</p>
{% endfor %}
for ... empty
可选的{ % empty % } 从句,给出的组是空的或者没有被找到时,执行的操作
{% for food in foods_list %}
<p>{{ food }}</p>
{% empty %}
<p>没有foods_list,或者foods_list为空</p>
{% endfor %}
for循环的其他方法
forloop.counter 当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(从1开始)
forloop.revcounter0 当前循环的倒序索引值(从0开始)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等
forloop.parentloop.counter
if 标签
对一个变量求值,如果它的值是“True” (存在,不为空,且不是boolean类型的False值),对应的内容块会输出。
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。
{% if num > 100 or num < 0 %}
<p>条件1满足</p> <!--不满足条件,不会生成这个标签-->
{% elif num > 80 and num < 100 %}
<p>条件1不满足,条件2满足</p>
{% else %} <!--也是在if标签结构里面的-->
<p>条件都不成立,执行我吧</p>
{% endif %}
with 标签
给一个复杂的变量起别名
{% with total=business.employees.count %}
{{ total }} <!--只能在with语句体内用-->
{% endwith %}
或者
{% with business.employees.count as total %}
{{ total }}
{% endwith %}
csrf_token 标签
用于跨站请求伪造保护
在form表单里面任何位置写上。
工作原理:
1、在GET请求到form表单时,标签{% csrf_token%}会被渲染成一个隐藏的input标签,该标签包含了由服务端生成的一串随机字符串,如下:
<input type="hidden" name="csrfmiddlewaretoken" value="dmFo...O5">
2、在使用form表单提交POST请求时,会提交上述随机字符串,服务端在接收到该POST请求时会对比该随机字符串,对比成功则处理该POST请求,否则拒绝,以此来确定客户端的身份
实例:
<form action="" method="post">
{% csrf_token %}
用户名:<input type="text">
密码:<input type="password">
<input type="submit">
</form>
五、自定义过滤器和标签
当内置的过滤器和标签无法支持我们的需求时,就使用自定义标签或过滤器
自定义过滤器
步骤:
1、在文件夹app01中创建子文件夹 templatetags (文件夹只能是templatetags)
2、在 templatetags 新建任意 .py 文件,如 mytags.py,在该文件中自定义过滤器或标签。
内容如下
# mytags.py 文件
from django import template # 导入的模块
register = template.Library() # register 固定的名字 注册器
# 自定义过滤器
@register.filter
def my_filter1(v1): # 不带参数的
# 对 v1 的操作
v = v1 + '操作'
return v
"""
使用:HTML文件中
{% load 文件名 %} --> 在HTML文档中必须先加载存有自定义过滤器和标签的文件
{{ value1|my_filter1 }} --> 无参数
把 value1 的值传入给 v1 ,做处理后返回。
"""
@register.filter
def my_filter2(v1, v2): # 带参数的过滤器(最多只能带两个)
# 对 v1 v2 的操作
v = v1 + v2
return v
"""
使用:HTML文件中
{% load 文件名 %} --> 在HTML文档中必须先加载存有自定义过滤器和标签的文件
{{ value1|my_filter1:value2 }} --> 有参数
把 value1 的值传给 v1 ,参数 value2 传给 v2 ,做处理后返回
"""
自定义标签
步骤和自定义过滤器一样:
# mytags.py 文件
from django import template # 导入的模块
register = template.Library() # register 固定的名字 注册器
@register.simple_tag
def my_tag(v1, v2, v3): # 自定义的标签可以定义多个参数
# 对传入的参数处理
v = v1 + v2 + v3
return v
"""使用:HTML文件中
{% load 文件名 %} --> 在HTML文档中必须先加载存有自定义过滤器和标签的文件
{% my_tag value1 value2 value3 %}
把 value1=v1 value2=v2 value3=v3 传入标签中,处理后返回。
"""
六、模板继承
在Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的 “骨架” 模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks 。
模板主要围绕三种标签的使用:include标签、extends标签、block标签。
模板继承之include标签
include标签也称为组件
组件和插件的简单区别:
- 组件是提供某一完整功能的模块。
- 而插件更倾向于封闭某一功能方法的函数。
作用:在一个HTML模板文件中,引入或者重复使用另一个模板文件的内容。
{% include '模板名称' %}
实例:
把整个 test.html 模板引入到 index.html 模板中
<!-- test.html 文件 -->
<div>
<ul>
<li>小杨</li>
<li>小明</li>
<li>鲍勃</li>
<li>艾伦</li>
</ul>
</div>
<!------------------------------------------------------------------------>
<!-- index.html 文件 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
{% include 'test.html' %} <!-- 此处,当此文件发送给客户端的时候,就变成了test.html文件的内容了 -->
</div>
</body>
</html>
模板继承之extends标签、block标签
作用:在一个HTML模板文件中,引入或者重复使用另一个模板文件的内容。
include 有的功能 extends 全都有,但是 extends 可以搭配一个block标签,用于在继承的基础上增加新的内容
模板制定钩子
{% block 钩子名 %}
<!-- 另一HTML模板引入此模板时可以从此处填充自己的内容 -->
{% endblock 钩子名 %}
新模板引入旧模板,并从旧模板钩子处填充新内容
{% extends '模板名' %}
<!-- 用新内容完全覆盖了父模板钩子中的内容 -->
{% block 钩子名 %}
<p> Hello World... </p>
{% endblock 钩子名 %}
实例:
1、制定一个模板 base.html ,它定义了一个页面上面的导航栏,和页面左边的菜单栏,网页中间由我们引入模板时自行填充自己的内容。
|---------------------|
| 导航栏 |
|-------|-------------|
| 菜 | |
| 单 | 自行填充的内容 |
| 栏 | |
|-------|-------------|
模板 base.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.top {
height: 100px;
background-color: red;
}
.left {
height: 400px;
width: 20%;
background-color: aqua;
float: left;
}
.centre {
float: right;
height: 400px;
width: 80%;
background-color: green;
}
</style>
</head>
<body>
<div class="top">
<a href="">导航一</a>
<a href="">导航二</a>
<a href="">导航三</a>
<a href="">导航四</a>
</div>
<div class="counter">
<div class="left">
<p><a href="">菜单一</a></p>
<p><a href="">菜单二</a></p>
<p><a href="">菜单三</a></p>
<p><a href="">菜单四</a></p>
</div>
<div class="centre">
{% block centent %}
<ul>
<li>信息1</li>
<li>信息2</li>
<li>信息3</li>
</ul>
<!-- 另一HTML模板引入此模板时可以从此处填充自己的内容 -->
{% endblock centent %}
</div>
</div>
</body>
</html>
2、index.html 模板引入base.html 模板,并在 base.html 模板钩子处添加新内容。
{% extends 'base.html' %}
{% block centent %}
{{ block.super }} ————> 该变量会将父模板中 centent 中原来的内容继承过来
<!--在继承父模板内容的基础上新增的标签-->
<form action="" method="post">
{% csrf_token %}
用户名:<input type="text">
密码:<input type="password">
<input type="submit">
</form>
{% endblock centent %}
3、当启动 Django 访问 index.html 页面时返回的内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.top {
height: 100px;
background-color: red;
}
.left {
height: 400px;
width: 20%;
background-color: aqua;
float: left;
}
.centre {
float: right;
height: 400px;
width: 80%;
background-color: green;
}
</style>
</head>
<body>
<div class="top">
<a href="">导航一</a>
<a href="">导航二</a>
<a href="">导航三</a>
<a href="">导航四</a>
</div>
<div class="counter">
<div class="left">
<p><a href="">菜单一</a></p>
<p><a href="">菜单二</a></p>
<p><a href="">菜单三</a></p>
<p><a href="">菜单四</a></p>
</div>
<div class="centre">
<!-- 此处被替换 -->
<form action="" method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="WE..DF">
用户名:<input type="text">
密码:<input type="password">
<input type="submit">
</form>
</div>
</div>
</body>
</html>
总结:
- 标签extends必须放在首行,base.html 中 block 越多控制性越强
- include 仅仅只是完全引用了其他模板文件,而 extends 却可以搭配 block 在引用的基础上进行扩写
- 变量 {{ block.super }} 可以重用父类的内容,然后再父类基础上增加新内容,而不是完全覆盖
- 在一个模板中不能出现重名的block标签。
七、静态文件配置
在网站中我们需要用到大量的css、js、图片等,这些都叫做静态文件。
关于Django中静态文件的配置,我们就需要在 settings 配置文件里面写上这样的内容:
1、例如在项目中创建一个 static_file 文件夹来存放静态文件。
注意:别名可以随便写名字,但是如果改了名字,别忘了如果前端页面如果是通过 /别名/静态文件
调用静态文件的话,前端页面的静态文件也要更改成一样的
STATIC_URL = '/static/' # 别名
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static_file')
]
2、前端页面引入静态文件
方式一:不推荐,别名如果有变化,所有应用别名的地方都需要改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/css/my.css">
</head>
<body>
<h1 class="c1" id="d1">点我就弹窗</h1>
<img src="/static/img/my.png" alt="">
<script src="/static/js/my.js"></script>
</body>
</html>
方式二:推荐,通过 load static 来找到别名,通过别名映射路径的方式来获取静态文件
标签static会接收传入的参数,然后这根据settings.py中变量STATIC_URL的值拼接出一个完整的路径
{% load static %} <!-- 注意:必须先加载文件static.py -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 注意:此处的static是一个定义在 static.py 中的一个标签,名字与文件名一样 -->
<link rel="stylesheet" href="{% static 'css/my.css' %}">
</head>
<body>
<h1 class="c1" id="d1">点我就弹窗</h1>
<img src="{% static 'img/my.png' %}" alt="">
<script src="{% static 'js/my.js' %}"></script>
</body>
</html>
方式三:get_static_prefix 标签
和上面的效果一样,不过只是用法不同。get_static_prefix 不能传参,只能拼接,如下:
{% load static %} <!-- 注意:必须先加载文件static.py -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% get_static_prefix %}css/my.css">
</head>
<body>
<h1 class="c1" id="d1">点我就弹窗</h1>
<img src="{% get_static_prefix %}img/my.png" alt="">
<script src="{% get_static_prefix %}js/my.js"></script>
</body>
</html>