006 Django 模板层
模板层
目录
模板配置
- 创建模板文件夹
<项目名>/templates
- 在
settings.py
中TEMPLATES
配置项- BACKEND: 指定模板的引擎
- DIRS: 模板的搜索目录(可以是一个也可以是多个)
- APP_DIRS: 是否要在应用中的 templates 文件夹中搜索模板文件
- OPTIONS: 有关模板的选项
- 配置项中需要修改的部分
- 设置DIRS -
‘DIRS’:[os.path.join(BASE_DIR, ‘templates’)]
- 设置DIRS -
例子
默认没有添加os标准库,请自行在 settings.py 文件的顶部添加
- 回到项目的根目录,创建一个
templates
文件夹
加载模板
loader方法
我们通过 loader 获取模板,通过 HttpResponse 进行响应,在视图函数中
from django.template import loader
# 通过loader加载模板
t = loader.get_template("模板文件名")
# 将 t 转换成 HTML 字符串
html = t.render(字典数据)
# 用响应对象将转换的字符串内容返回给浏览器
return HttpResponse(html)
例子
- 在模板文件夹中添加我们需要的新页面
test_html.html
- 在视图层添加一个新的函数用来读取我们的模板
# views.py 文件内
from django.template import loader
from django.http import HttpResponse
def test_html(request):
t = loader.get_template("test_html.html")
html = t.render()
return HttpResponse(html)
- 在路由文件内添加地址
# urls.py 文件内
from django.urls import path
from . import views
urlpatterns = [
path('testHtml',views.test_html)
]
- 浏览地址打开
render方法(推荐)
我们可以使用 render()直接加载并且响应模板
在视图文件中
from django.shortcuts import render
return render(request, "模板文件名",字典数据)
例子
- 在模板文件夹中添加我们需要的新页面
test_html.html
- 在视图层添加一个新的函数用来读取我们的模板此处进行了简化和包装
# views.py 文件内
from django.shortcuts import render
from django.http import HttpResponse
def test_html(request):
# 注意这里进行了简化和包装
return render(request, "test_html,html")
- 在路由文件内添加地址
# urls.py 文件内
from django.urls import path
from . import views
urlpatterns = [
path('testHtml',views.test_html)
]
- 浏览地址打开
视图与模板层之间的交互
- 视图函数中可以将 Python 变量封装到字典中传递到模板
样例:
def xxx_view(request):
dic = {
"变量1":"值1",
" 变量2":"值2"
}
return render(request,'xxx.html',dic)
- 在模板中我们则可以使用
{{变量名}}
这样的方法调用视图传递进来的变量
使用模板例子
- 设置视图层函数,在视图层定义指定字典然后通过
render()
函数传递出去
# views.py文件内
from django.shortcuts import render
def testTemplate(request):
dic = {
"name":"张飞",
"age":"18"
}
return render(request,"test_template.html",dic)
- 新建 HTML 文件
- 设置路由
# urls.py 文件内
from django.urls import path
from . import views
urlpatterns = [
path('testTemplate', views.test_template),
]
- 打开网页发现内容已经被填充到网页
模板的变量
能够传递到模板中的数据类型不止 dict
,其他的数据类型同样可以传递
类型 | 说明 |
---|---|
str | 字符串 |
int | 整型 |
list | 数组 |
tuple | 元组 |
dict | 字典 |
func | 方法 |
obj | 类实例化的对象 |
- 如果传入的是一个列表
- 使用
{{ 变量名.index }}
的方式调用,而不是变量名[index]
- 使用
- 如果传进来的字典内部还有一个字典
- 使用
{{ 变量名.key }}
来调用对应的值
- 使用
- 如果传入的是一个实例化的对象
- 使用
{{ 对象.方法 }}
来调用
- 使用
- 如果传入的是一个函数
- 使用
{{函数名}}
在模板中就会直接调用函数并且返回返回值
- 使用
- 视图函数中设置的 dic
- 模板 html 文件内的内容
- 最终页面的内容
模板标签
作用:将一些服务器端的功能嵌入到模板中,例如流程控制等
标签语法:
{% 标签 %}
...
{% 结束标签 %}
if 标签
{% if条件表达式1 %}
...
{% elif条件表达式2 %}
...
{% elif条件表达式3 %}
...
{% else %}
...
{% endif %}
- if条件表达式里可以用的运算符==,!=,<,>, <=, >=, in, not,in, is, is not, not、 and、or
- 在if标记中使用实际括号是无效的语法。如果您需要它们指示优先级,则应使用嵌套的if标记。
可视化计算器练习
- 创建
mycal.html
页面
<form action='/mycal' method='post'>
<input type='text' name="x" value={{ x }}>
<select name='op'>
<option value="add"> +加</option>
<option value="sub"> -减</option>
<option value="mul"> *乘</option>
<option value="div"> /除</option>
</select>
<input type='text' name="y" value={{ y }}> = <span>{{ result }}</span>
<div>
<input type="submit" value='开始计算'>
</div>
</form>
- 在视图界面创建一个函数负责接收计算然后返回页面
# views,py 文件内
from django.shortcuts import render
def my_cal(request):
# 获取数值
if request.method == "POST":
x = int(request.POST.get("x",'0'))
y = int(request.POST.get("y",'0'))
op = request.POST.get("op",'add')
if op == 'add':
result = str(x + y)
elif op == 'sub':
result = str(x - y)
elif op == 'mul':
result = str(x * y)
elif op == 'div':
result = str(x / y)
# 创建字典返回给页面
dic = {
'result': result,
'y': y,
'x': x,
}
return render(request,'mycal.html',dic)
return render(request,"mycal.html")
- 在路由内设置
# urls.py 文件内
from django.urls import path
from . import views
urlpatterns = [
path('testTemplate', views.test_template)
]
- 页面内查看效果
- 小技巧
我们在拼接字典的过程中绝对非常麻烦的可以尝试使用 python自带的函数 locals()
,可以把当前函数内的变量打包成字典,就可以直接返回给我们的前端
loacls() 使用
def a():
a = 1
b = 2
c = {'a': 1, 'b':4}
return locals()
print(a())
- 最终打印的结果
{'a': 1, 'b': 2, 'c': {'a': 1, 'b': 4}}
- 我们使用 locals() 后就不需要我们再手动写字典了
def my_cal(request):
# 获取数值
if request.method == "POST":
x = int(request.POST.get("x",'0'))
y = int(request.POST.get("y",'0'))
op = request.POST.get("op",'add')
if op == 'add':
result = str(x + y)
elif op == 'sub':
result = str(x - y)
elif op == 'mul':
result = str(x * y)
elif op == 'div':
result = str(x / y)
# 此处我们就直接传入 locals()即可
return render(request,'mycal.html',locals())
return render(request,"mycal.html")
for 标签
{% for变量in可迭代对象%}
... 循环语句
{% empty %}
... 可迭代对象无数据时填充的语句
{% endfor %}
其中的 empty 表示的如果我们的可迭代对象是空,django就会显示我们的empty下面的内容
内置变量 forloop
这些变量都需要写在 for 循环内部,如果写在外部就直接报错
变量 | 说明 |
---|---|
forloop.counter | 循环的当前迭代(从1开始索引) |
forloop.counter0 | 循环的当前迭代(从0开始索引) |
forloop.revcounter | counter值的倒序 |
orloop.revcounter0 | revcounter值的倒序 |
forloop.first | 如果这是第一次通过循环,则为真 |
forloop.last | 如果这是最后一次循环, 则为真 |
forloop.parentloop | 当嵌套循环,parentloop 表示外层循环 |
for 循环例子1
- 给 HTML 模板(创建文件
testfor.html
)
{% for i in name %}
<p>{{i}}</p>
{% empty %}
当前没有发现任贺数据
{% endfor %}
- 给我们的视图添加函数
# views.py 文件内
from django.shortcuts import render
def testfor(request):
name = ['虎晶瑶','胡奇迈','闭昆皓','黄蝶']
return render(request,'testfor.html',locals())
- 添加路由
# urls.py 文件内
from django.urls import path
from . import views
urlpatterns = [
path('testfor',views.testfor)
]
- 查看页面
for 循环例子2
我们在上面的基础上添加一些新的需求,使用我们的forloop
变量
- 我们循环的第一次打印打印头
if forloop.first
{% for i in name %}
{% if forloop.first %} 当前是第一次循环 {% endif %}
<p>{{i}}</p>
{% empty %}
当前没有发现任贺数据
{% endfor %}
- 我们结尾的时候也打印特殊的内容
if forloop.last
{% for i in name %}
{% if forloop.first %} 当前是第一次循环 {% endif %}
<p>{{i}}</p>
{% if forloop.last %} 当前循环结束了 {% endif %}
{% empty %}
当前没有发现任贺数据
{% endfor %}
- 打印我们当前的项是第几个
{{forloop.counter}}
{% for i in name %}
{% if forloop.first %} 当前是第一次循环 {% endif %}
<p>{{forloop.counter}} {{i}}</p>
{% if forloop.last %} 当前循环结束了 {% endif %}
{% empty %}
当前没有发现任贺数据
{% endfor %}
模板过滤器
- 定义:在变量输出时对变量的值进行处理
- 作用:可以通过使用过滤器来改变变量的输出显示
- 语法:
{{变量|过滤器1:'参数值1|过滤器2:'参数值2'}}
常用模板过滤器
模板过滤器 | 说明 |
---|---|
lower | 将字符串转换为全部小写。 |
upper | 将字符串转换为大写形式 |
safe | 默认不对变量内的字符串进行htmI转义 |
add: "n" | 将value的值增加n |
truncatechars:'n' | 如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(...") 结尾。 |
upper 模板过滤器
- 没有加模板过滤器之前
<h3>str 是{{ str }}</h3>
- 添加模板过滤器之后
<h3>str 是{{ str|upper }}</h3>
add 模板过滤器
- 没有加模板过滤器之前
<h3>int是{{ int }}</h3>
- 添加模板过滤器之后
<h3>int是{{ int|add:"2" }}</h3>
模板的继承
大多数的网站头部和尾部基本都是一样的,我们这个时候就可以使用模板的继承来让一个页面内相同的内容继承
模板继承可以使父模板的内容重用,子模板直接继承父模板的全部内容并可以覆盖父模板中相应的块
语法-父模板中:
- 定义父模板中的块block标签
- 标识出哪些在子模块中是允许被修改的
- block标签:在父模板中定义,可以在子模板中覆盖
语法 - 子模板中:
- 继承模板extends标签(写在模板文件的第一行)
- 例如
{% extends 'base.html' %}
- 例如
- 子模板重写父模板中的内容块
{% block block_ name %}
子模板块用来覆盖父模板中block_ name块的内容
{% endblock %}
例子
- 新建一个父模板
base_index.html
文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% block title %}
<title>Document</title>
{% endblock %}
</head>
<body>
<!-- 导航条 -->
<a href="/music">音乐频道</a>
<a href="/base_index">返回首页</a>
{% block content %}
<p>这里是首页</p>
<p>这里是首页</p>
{% endblock %}
<p>页尾:如果有问题请联系xxx</p>
</body>
</html>
- 创建子模板
music.html
,然后删除所有 html 元素,并且在最开头继承我们的父模板
{% extends "base_index.html" %}
{% block title %}
<title>这里是音乐页面</title>
{% endblock %}
{% block content %}
<p>这是音乐页面</p>
{% endblock %}
- 新建视图函数
# views.py 文件内
from django.shortcuts import render
def base_index(request):
return render(request,'base_index.html')
def music(request):
return render(request,'music.html')
- 在主路由内添加我们的路由记录
# urls.py 文件内
from django.urls import path, re_path
from . import views
urlpatterns = [
path('base_index',views.base_index),
path('music',views.music)
]
- 打开浏览器查看效果