django之模板层
什么是模板层
模板层是在视图函数中被用作渲染的html文件,后端中的数据常常需要动态的传递到前端中。后端我们使用的python语法,而前端使用的是html语言。我们知道想让前端数据传递到后端,只需将数据在GET或者POST中携带。那后端如何将数据传递到前端呢?
我们在视图层可以将HttpResponse或者JsonResponse直接将数据进行返回,但这不能满足前端胡里花哨的页面显示。
有没有可能先制作好html文件,然后在其中预留一些位置,我们后端再将数据填入这些空白中呢?
答案是肯定的。这就是django中的模板层,当然我们得遵循模板层特有的语法。
1.模板语法符号
{{ }}:变量相关
{% %}:逻辑相关
python基本数据类型全部支持传递给html文件。
views.py
-------------------
def index(request):
my_dict = {
'user': 'yyh',
'password': 123,
'age': 18
}
return render(request, 'index.html', {'my_dict': my_dict})
# return render(request,'index.html',locals()) locals()会将函数命名空间内的所有变量名全部传递到index.html中
index.html
-------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body>
<p>{{ my_dict }}</p>
<p>{{ my_dict.user }}</p>
<p>{{ my_dict.password }}</p>
{% for key in my_dict %}
{{ key }}
{{ my_dict.key }}
{% endfor %}
{% for key,value in my_dict.items %}
{{ key }}
{{ value }}
{% endfor %}
<br>
{{ my_dict.hobbies.1.1 }}
{# my_dict.values my_dict.items #}
</body>
</html>
可以看到只能模板语法不管是列表还是字典都只能通过 . 的方式取值。
2.模板语法之过滤器
|length
|add
|default
|truncatechars
|truncatewords
|filesizeformat
|slice
|date
|safe
<p>过滤器 |左边的会当做过滤器的第一个参数 过滤器名右边的会当做过滤器的第二个参数</p>
<p>求数据长度:{{ s|length }}</p>
<p>加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}</p>
<p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}</p>
<p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}</p>
<p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}</p>
<p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}</p>
<p>转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}</p>
3.前后端取消转义
后端
----------
def login(request):
s = '<h1>hello world</h1>'
return render(request,'login.html',locals())
前端
-------
<body>
{{ s }}
</body>
---------# 浏览器将显示'<h1>hello world</h1>'
----------
<body>
{{ s|safe }}
</body>
---------- # 浏览器将以h1渲染helloworld
取消转义可以在前端完成,也可以在后端完成
from django.utils.safestring import mark_safe
def login(request):
s = '<h1>hello world</h1>'
s = mark_safe(s)
return render(request, 'login.html', locals())
----------------
<body>
{{ s }}
</body>
4.模板语法之标签
{% for foo in l %}
<p>{{ forloop }}</p>
{% endfor %}
{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 6, 'revcounter0': 5, 'first': True, 'last': False}
{'parentloop': {}, 'counter0': 1, 'counter': 2, 'revcounter': 5, 'revcounter0': 4, 'first': False, 'last': False}
{'parentloop': {}, 'counter0': 2, 'counter': 3, 'revcounter': 4, 'revcounter0': 3, 'first': False, 'last': False}
{'parentloop': {}, 'counter0': 3, 'counter': 4, 'revcounter': 3, 'revcounter0': 2, 'first': False, 'last': False}
{'parentloop': {}, 'counter0': 4, 'counter': 5, 'revcounter': 2, 'revcounter0': 1, 'first': False, 'last': False}
{'parentloop': {}, 'counter0': 5, 'counter': 6, 'revcounter': 1, 'revcounter0': 0, 'first': False, 'last': True}
模板语法中的for循环自带有一个forloop的对象,可以通过使用这个对象对for循环进行一些处理。
{% for foo in l %}
{% if forloop.first %}
<p>第一次循环噢</p>
{% elif forloop.last %}
<p>最后一次循环哦</p>
{% else %}
<p>{{ foo }}</p>
{% endif %}
{# 在l为空时执行#}
{% empty %}
<p>haa</p>
<p>haa</p>
{% endfor %}
# 可用add来判断第几次循环
{% for foo in l %}
{% if forloop.counter|add:-2 %}
{{ foo }}
{% endif %}
{# 在l为空时执行#}
{% empty %}
<p>haa</p>
{% endfor %}
</body>
</html>
5.自定义过滤器
自定义过滤器 标签 inclusion_tag
先完成以下前期准备工作
1.在应用名下新建一个名字必须叫templatetags文件夹
2.在该文件夹内新建一个任意名称的py文件(eg:mytag)
3.在该文件内 必须先写以下两句代码
from django.template import Library
register = Library()
# 自定义过滤器
@register.filter(name='my_sum')
def index(a,b):
return a + b
# 自定义标签
@register.simple_tag(name='my_baby')
def xxx(a,b,c,d):
return '%s?%s?%s?%s'%(a,b,c,d)
# 自定义inclusion_tag
@register.inclusion_tag('demo.html',name='myin')
def index1(n):
l = []
for i in range(n):
l.append(i)
# 将列表传递给demo.html
# return locals()
return {'l':l}
<p>自定义过滤器的使用</p>
{% load mytag %}
<p>{{ 10|my_sum:90 }}</p>
<p>自定义标签的使用</p>
{% load mytag %}
<p>{% my_baby 1 2 3 'hello world' %}</p>
<p>自定义的过滤器可以在逻辑语句中而自定义的标签不可以</p>
{% if 10|my_sum:100 %}
<p>条件成立</p>
{% endif %}
{% if my_baby 1 2 3 4 %}
<p>条件成立</p>
{% endif %}
<p>自定义inclusion_tag的使用</p>
{% load mytag %}
{% myin 5 %}
# 总结 页面上使用他们 统一先导入
{% load mytag %}
6.模板的继承
模板的继承实际上是在一个html模版上用 {% block 名字%}{% endblock %}
来划分一块区域。其他的html模板可以通过{% extends 'index.html' %},然后
{% block 名字%}{% endblock %}可以继承index.html里的代码,并将自己的block填充。{{block.super}}可以调用父页面对应区域的内容(在哪个block下使用就调用哪一块)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<link href="/static/bootstrap-3.3.7-dist/css/bootstrap.css" rel="stylesheet">
<script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
{% block css %}
{% endblock %}
</head>
<body>
{# 导航条样式 #}
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<div class="list-group">
{% block list_style %}
<a href="/index/" class="list-group-item active" id="id_index">
首页
</a>
<a href="/login/" class="list-group-item" id="id_login">登录</a>
<a href="/register/" class="list-group-item" id="id_register">注册</a>
{% endblock %}
</div>
</div>
<div class="col-md-9">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body panel-primary">
{% block content %}
{% endblock %}
{# <div class="jumbotron">#}
{# <h1>Hello, world!</h1>#}
{# <p>...</p>#}
{# <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>#}
{# </div>#}
</div>
</div>
</div>
</div>
</div>
{% block js %}
<script>
$('#id_index').addClass('active').siblings().removeClass('active')
</script>
{% endblock %}
</body>
</html>
login.html
{% extends 'index.html' %}
{#{% block list_style %}#}
{#<a href="/index/" class="list-group-item">#}
{#首页#}
{#</a>#}
{#<a href="/login/" class="list-group-item active">登录</a>#}
{#<a href="/register/" class="list-group-item">注册</a>#}
{#{% endblock %}#}
{% block css %}
<style>
</style>
{% endblock %}
{% block content %}
<h1 class="text-center">登录</h1>
<p>用户名:<input type="text"></p>
<p>密码:<input type="password"></p>
<button class="btn btn-danger">提交</button>
{% endblock %}
{% block js %}
<script>
$('#id_login').addClass('active').siblings().removeClass('active')
</script>
{% endblock %}
7.模板的导入
django还支持将html页面当做模块使用,哪里需要导哪里,被导入的这个html文件通常是不完整的。
{% include 'left.html' %}