🍖Django框架之模板层
一.两种模板方法
-
变量相关 :
{{ }}
-
逻辑相关 :
{% %}
二.注释
- 注释是代码之母 :
{# #}
三.模板语法之传值
1.Python中基本数据类型传值
def test_func(request):
s = "Hello 派大星!"
i = 1314520
f = 1.75
l = [1,2,3,4,5]
d = {"name":"shawn","age":23}
t = (2,3,4,5,5)
se = {3,4,5,'rr'}
b = True
# 传值方式一 : 使用字典的格式一个个传
return render(request,'test.html',{'strs':s,'ints':i,'lists':l,...})
# 传值方式二 : 使用 locals()将当前名称空间所有的变量名全部传递微页面
return render(request,'test.html',locals())
- test.html 文件
<h1>{{ s }}</h1>
<h1>{{ i }}</h1>
<h1>{{ f }}</h1>
<h1>{{ l }}</h1>
<h1>{{ d }}</h1>
<h1>{{ t }}</h1>
<h1>{{ se }}</h1>
<h1>{{ b }}</h1>
2.函数与类的传递
def test_func(request):
def aa():
print("aa--->")
return 'I am aa'
class Bar(object):
def cc(self):
print("Bar-->cc")
B1 = Bar()
return render(request, 'test.html', locals())
- 模板层
<h1>{{ aa }}</h1>
<h1>{{ Bar }}</h1>
<h1>{{ B1 }}</h1>
3.函数名与类名注意点
- 传递函数名与类名都会自动加括号调用
- 传入函数名得到的结果是函数的返回值
- 模板语法不支持额外的传参,也就是函数无法传参
4.传值方式优缺点 :
- 传值方式一 : 传值精确, 不会造成资源浪费
- 传值方式二 : 传值简单, 可能造成一定的资源浪费
四.模板语法之获取值
-
django模板语法取值只能采用句点符(.),也就是点
-
可以根据索引以及键取值,支持多个很多个点........
# views.py
def test_func(request):
ll = [1,2,{"name":"shawn","age":23,"hobby":["read","study"]}]
return render(request,"test.html",{"ll":ll})
# 想要取出爱好read
# test.html
<h1>{{ ll.2.hobby.0 }}</h1>
五.模板语法之过滤器Filter
1.过滤器说明
- 类似于Python的内置方法
- 将竖杠左侧的数据当做第一个参数传给右边的过滤器
- 语法 :
{{ [数据]|过滤器:可选参数 }}
- 注意 : 竖杠左右两边没有空格
- 过滤器参数包含空格的话需要使用引号包裹
- 过滤器最多只能有两个参数
2.常用过滤器使用
- django中大约60中过滤器,下面只介绍常用过滤器
# views.py
def test_func(request):
s = "Hello 派大星!"
i = 1314520
f = 1.75
l = [1,2,3,4,5]
d = {"name":"shawn","age":23}
t = (2,3,4,5,5)
se = {3,4,5,'rr'}
b = True
w = 'aa bb cc dd ee ff'
return render(request,'test.html',locals())
<!-- test.html-->
<p>统计长度:{{ s|length }}</p>
<!-- add数字相加,字符拼接-->
<p>加法运算:{{ i|add:1000 }}</p>
<p>字符串拼接:{{ s|add:'Hello 海绵宝宝' }}</p>
<p>拼接:{{ s|join:'@' }}</p>
<p>切片:{{ l|slice:'0:5:2' }}</p>
<p>日期格式:{{ ctime|date:'Y年-m月-d日 H时:i分:s秒' }}</p>
<!-- 如果第一个参数的布尔值是true则显示左边的值,否则显示default后的值-->
<p>默认值:{{ b|default:'哈哈' }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<!-- 截取内容包含三个点,并且算在字符个数之内-->>
<p>截取文本:{{ w|truncatechars:6 }}</p>
<!-- 截取内容包含三个点,但不算在单词个数之内,单词识别是以空格来区分的-->
<p>截取单词:{{ w|truncatewords:3 }}</p>
3.转意
- 后端使用转意
from django.utils.safestring import mark_safe
html_safe = mark_safe('<h1>你好</h1>')
- 前端使用转意
{{ html|safe }}
六.模板语法之标签
类似于Python中的流程控制
1.for循环
{% for i in l %}
<p>{{ forloop }}</p>
<p>{{ i }}</p> # 循环从列表 l 中取出一个个元素
{% endfor %}
我们再看看 forloop 输出的是什么:
2.if 判断
# i = 90
{% if i > 100 %}
<p>is True</p>
{% elif i > 80 %}
<p>is two</p>
{% else %}
<p>is no</p>
{% endif %}
3.for 与 if 混合使用
{% for i in l %}
{% if forloop.first %}
<p>is first</p>
{% elif forloop.last %}
<p>is last</p>
{% else %}
<p>{{ i }}</p>
{% endif %}
{% endfor %}
4.empty : 空
{% for foo in request %}
{% empty %}
<p>传入的数据为空,无法进行循环</p>
{% endfor %}
5.with : 取别名
{% with ll.2.hobby.0 as hb %}
<p>{{ hb }}</p> # 可以使用别名取值
<p>{{ ll.2.hobby.0 }}</p> # 也可以使用原来的方式取值
{% endwith %}
6.字典values、keys、items方法
{% for k in d.keys %}
<p>{{ k }}</p>
{% endfor %}
{% for v in d.values %}
<p>{{ v }}</p>
{% endfor %}
{% for kv in d.items %}
<p>{{ kv }}</p>
{% endfor %}
七.自定义过滤器、标签、inclusion_tag
类似于Python中的自定义函数
1.创建 templatetags 文件
- 首先在应用下创建一个名字必须叫"templatetags"文件夹
- 在改文件夹下创建一个任意名称的 py 文件 (例 : mytag)
- 在该 py 文件内固定书写两行代码
from django import template
register = template.Library()
2.自定义过滤器
- 自定义过滤器最多只能有两个形参
from .templatetags.mytag import register
# 在模板层导入自定义的过滤器时使用的是这里指定的名字
@register.filter(name='myfilter')
def sums(a, b): # 函数名随便起什么
return a + b # 返回两个参数的和
{% load mytag %} # 导入tag文件
<p>{{ i|myfilter:100 }}</p> # 使用myfilter过滤器
3.自定义标签
- 自定义标签可以有多个参数
from .templatetags.mytag import register
# 在模板层导入自定义的标签时使用的是这里指定的名字
@register.simple_tag(name="my_tag")
def my_join(a,b,c,d): # 函数名任意
return f'{a}/{b}/{c}/{d}' # 返回参数拼接后的结果
{% load mytag %} # 导入tag文件
<p>{% my_tag 'hello' 'pai' 'da' 'xing' %}</p> # 标签之后的多个参数彼此之间用空格隔开
- 示例二
from .templatetags.mytag import register
# 在模板层导入自定义的标签时使用的是这里指定的名字
@register.simple_tag(name="my_tag")
def my_join(a,b): # 函数名任意
return a+b # 返回和
{% load mytag %}
<p>{% my_tag i 100 %}</p>
4.自定义 inclusion_tag
- inclusion_tag 的内部原理:
- 在HTML页面中导入写好的 inclusion_tag 并调用了
- 触发了py文件中一个函数的执行并产生结果
- 产生的结果通过模板语法传递给一个HTML页面进行渲染
- 渲染完毕后又返回调用 inclusion_tag 的位置
- 示例
from .templatetags.mytag import register
@register.inclusion_tag('test.html',name='my_incl_tag') # 第一个参数是需要渲染的HTML页面
def func(n):
data=[]
for i in range(n):
data.append(f'第{i}页')
return locals()
# test.html 文件
{% load mytag %}
<p>{% my_incl_tag 6 %}</p>
# test2.html
{{ data }}
{% for foo in data %}
{% if forloop.first %}
<p>{{foo}}</p>
{% elif forloop.last %}
<p>{{ foo }}</p>
{% else %}
<p>{{ foo }}</p>
{% endif %}
{% endfor %}
test.html 页面中调用了 inclusion_tag----->触发执行了一个函数产生结果并渲染到 test2.html 页面中, 渲染完又返回 test.html 页面
八.模板的导入
类似于后端的模块, 想要什么页面,局部直接导入即可
{% include 'edit.html' %} # 直接在当前HTML文件里面显示 edit.html 文件的内容
九.模板的继承
1.模板继承的使用
- 模板的继承首先需要选择一个模板页面, 在该页面里面使用 block 划定可以被更改的区域
# 母板页面 'home.html' 文件
{% block [区域名称] %}
......
{% endblock %}
- 想要继承的页面可以使用 extends 来继承某一个页面
# 子版
{% extends 'home.html' %}
{% block [区域名称] %}
......
{% endblock %}
子版继承了模板, 那么子版的整体格式与模板一样, 被 block 划分了的区域可以自己随意更改
2.模板的三个区域
- 母板在划分区域的时候一般有三个区域
{% block css %}
# css区域
{% endblock %}
{% block content %}
# HTML区域
{% endblock %}
{% block js %}
# js区域
{% endblock %}
目的是为了让子版具有独立的css、js等,增加扩展性
- 子版也可以继续使用母版划定了区域内的内容
{{ block.super }}
3.示例
- 路由层
urlpatterns = [
path('admin/', admin.site.urls),
path('home/', views.func),
path('index/', views.func2,name='index_name'),
]
- 视图层
def func(request):
return render(request,'home.html')
def func2(request):
return render(request,'index.html')
- 模板层
# home.html
{% block left-body %}
<div class="jumbotron">
<h1>Hello, world!</h1>
<p>这里是一个block划分的区域</p>
<p><a class="btn btn-primary btn-lg" href="{% url 'index_name' %}" role="button">Learn more</a></p>
</div>
{% endblock %}
# index.html
{% extends 'home.html' %}
{% block left-body %}
<div class="row">
<div class="col-xs-6 col-md-4 col-md-offset-2">
<a href="#" class="thumbnail">
<img src="../static/img/11.png" alt="...">
</a>
</div>
<div class="col-xs-6 col-md-4 col-md-offset-2">
<a href="#" class="thumbnail">
<img src="../static/img/11.png" alt="...">
</a>
</div>
</div>
{% endblock %}
- home.html 页面
- index.html 页面
十.小练习
1.需求
-
將对用户增删改查的功能使用模板的继承来写
-
代码除了模板层与之前无太大差别
2.代码实现
- urls.py 文件
from django.contrib import admin
from django.urls import path,re_path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('home/', views.home_func,name='home_name'),
re_path('^edit/(\d+)', views.edit_func,name='edit_name'),
re_path('^del/(\d+)', views.del_func,name='del_name'),
path('insert/', views.insert_func,name='insert_name'),
]
- views.py 文件
def home_func(request):
user_obj_list = models.User.objects.all()
return render(request,'home.html',locals())
def edit_func(request,id):
if request.method == "POST":
name = request.POST.get('name')
pwd = request.POST.get('pwd')
age = request.POST.get('age')
models.User.objects.filter(id=id).update(name=name,pwd=pwd,age=age)
return redirect('home_name')
user_obj = models.User.objects.filter(id=id).first()
return render(request,'edit.html',{'user_obj':user_obj})
def del_func(request,id):
models.User.objects.filter(id=id).delete()
return redirect('home_name')
def insert_func(request):
if request.method == "POST":
name = request.POST.get('name')
pwd = request.POST.get('pwd')
age = request.POST.get('age')
models.User.objects.create(name=name,pwd=pwd,age=age)
return redirect('home_name')
return render(request,'insert.html')
- 模板层文件
# home.html 文件
##[导航栏代码]
##[左侧边栏代码]
##[右边内容由block划分]
{% block left-body %}
<div class="container">
<div class="row">
<h1 class="text-center">用户数据</h1>
<div class="col-md-8 col-md-offset-2">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>密码</th>
<th>年龄</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for user_obj in user_obj_list %}
<tr>
<td>{{ user_obj.id }}</td>
<td>{{ user_obj.name }}</td>
<td>{{ user_obj.pwd }}</td>
<td>{{ user_obj.age }}</td>
<td>
<a href="{% url 'del_name' user_obj.id %}">删除</a>
<a href="{% url 'edit_name' user_obj.id %}">修改</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="col-md-8 col-md-offset-2">
<form action="{% url 'insert_name' %}" method="get">
<input type="submit" class="btn btn-block btn-warning" value="新增">
</form>
</div>
</div>
</div>
</div>
{% endblock %}
# edit.html 文件
{% extends 'home.html' %}
{% block left-body %}
<div class="container">
<div class="row">
<h2 class="text-center">修改数据</h2>
<div class="col-md-8 col-md-offset-2">
<form action="" method="post">
username:
<input type="text" name="name" class="form-control" value="{{ user_obj.name }}">
password:
<input type="text" name="pwd" class="form-control" value="{{ user_obj.pwd }}">
age:
<input type="number" name="age" class="form-control" value="{{ user_obj.age }}">
<input type="submit" value="提交" class="btn btn-block btn-warning">
</form>
</div>
</div>
</div>
{% endblock %}
# insert.html 文件
{% extends 'home.html' %}
{% block left-body %}
<div class="container">
<div class="row">
<h2 class="text-center">插入数据</h2>
<div class="col-md-8 col-md-offset-2">
<form action="" method="post">
username:
<input type="text" class="form-control" name="name">
password:
<input type="test" class="form-control" name="pwd">
age:
<input type="number" class="form-control" name="age">
<input type="submit" value="提交" class="btn btn-block btn-warning">
</form>
</div>
</div>
</div>
{% endblock %}