第六篇:Django之模板层
第六篇:Django之模板层
一、模板语法传值
模板语法简单来说,只有两种两种格式。
# 第一种
{{ }}:变量相关
# 第二种
{% %}:逻辑相关
模板语法可以传递后端的python数据类型给html页面。
下面我们进行一一测试python的数据类型是否可以通过模板语法传递。
我们在后端设置这样的数据,用来进行测试。
# 模板语法
def index(request):
# 我们先定义python中的数据类型
num = 111
flo = 222.2
bo = True
li = ['杨毅', '雷超', '安安', '杨鑫', '权康', '港川']
tup = ('小红', '小花', '小兰', '小紫', '小绿')
dic = {'username': '杨毅', 'age': 18, 'gender': '男'}
se = {'张无忌', '赵敏', '周芷若'}
def func():
return ('俺被执行了')
class MyClass(object):
def get_self(self):
return '绑定方法'
@staticmethod
def get_func():
return '静态方法'
@classmethod
def get_class(cls):
return '类方法'
# 对象被展示到html页面上 就类似于执行了打印操作也会触发__str__方法
def __str__(self):
return '到底会不会执行呢?'
obj = MyClass()
return render(request, 'index.html', locals())
我们的index.html页面中如此书写。
<p>整形:{{ num }}</p>
<p>浮点型:{{ flo }}</p>
<p>布尔值:{{ bo }}</p>
<p>列表:{{ li }}</p>
<p>元组:{{ tup }}</p>
<p>字典:{{ dic }}</p>
<p>集合:{{ se }}</p>
<p>函数:{{ func }}</p>
<p>类:{{ MyClass }}</p>
<p>对象:{{ obj }}</p>
<p>对象调用绑定方法:{{ obj.get_self }}</p>
<p>对象调用类方法:{{ obj.get_class }}</p>
<p>对象调用静态方法:{{ obj.get_func }}</p>
之后我们便可以在浏览器中渲染出这样的结果。
注意:
1、传递函数名会自动加括号调用,但是模版语法不支持给函数传额外的参数。【显示的是函数的返回值】
2、传类名的时候也会自动加括号调用(实例化)
3、模板语法内部能够自动判断出当前的变量名是否可以加括号调用,如果可以就会自动执行。【针对的是函数名和类名】
Django模板语法取值的取值
django模版语法的取值,是固定的格式,只能采用“句点符” 。【也可以点索引,真是天才呀,哈哈。】
<p>{{ d.username }}</p>
<p>{{ l.0 }}</p>
<p>{{ d.hobby.3.info }}</p> # 即可以点键也可以点索引 还可以两者混用
"""与jinja2模板语法不同"""
# jinja2模板语法和python语法极为类似。
"""
jinja2模板语法
{{ user }}
{{ user.get('username')}}
{{ user.age }}
{{ user['hobby'] }}
"""
二、模版语法之过滤器
过滤器就类似于是模版语法内置的内置方法,django内置有60多个过滤器,在这里,我们只需要了解10多个就足矣。日后碰见在进行记忆。
基本语法:
# 注意 ':'左右不能有空格
{{数据|过滤器:参数}}
使用方式:
"""我们views.py中这样设置"""
# 模板语法
def index(request):
msg = 'my name is yang and my age is 18'
is_true = False
file_size = 123465798
current_time = datetime.datetime.now()
li = ['新垣结衣', '石原里美', '迪丽热巴', '佟丽娅']
info = '任时光匆匆离去,我只在乎你,心甘情愿感受你的呼吸。'
num = 100
s = 'hello, '
h5 = '<h1>迪丽热巴</h1>'
js = '<script>alert("迪丽热巴")</script>'
from django.utils.safestring import mark_safe
res = mark_safe('<h1>新垣结衣</h1>')
return render(request, 'index.html', locals())
"""index.html中进行测试"""
# 内部就是len(msg)
<p>统计长度:{{ msg|length }}</p> # 统计长度:32
# 第一个参数布尔值是True就展示第一个参数的值,否则展示冒号后面的值
<p>默认值:{{ is_true|default:'啥也不是' }}</p> # 默认值:啥也不是
# 文件大小【可以自动进行格式转化】
<p>文件大小:{{ file_size|filesizeformat }}</p> # 文件大小:117.7 MB
# 日期格式化
<p>日期格式化:{{ current_time|date:'Y-m-d H:i:s' }}</p> # 日期格式化:2021-06-28 16:46:38
# 切片操作(支持步长)
<p>切片操作(支持步长):{{ li|slice:'0:4:2' }}</p> # 切片操作(支持步长):['新垣结衣', '迪丽热巴']
# 切取字符(包含三个点)
<p>切取字符(包含三个点):{{ info|truncatechars:9 }}</p> # 切取字符(包含三个点):任时光匆匆离...
# 切取单词(不包含三个点 按照空格切)
<p>切取单词(不包含三个点 按照空格切):{{ msg|truncatewords:4 }}</p> # 切取单词(不包含三个点 按照空格切):my name is yang ...
# 移除特定的字符
<p>移除特定的字符:{{ msg|cut:' ' }}</p> # 移除特定的字符:mynameisyangandmyageis18
# 拼接操作
<p>拼接操作:{{ li|join:'$' }}</p> # 拼接操作:新垣结衣$石原里美$迪丽热巴$佟丽娅
# 拼接操作(加法)
<p>拼接操作(加法):{{ num|add:10 }}</p> # 拼接操作(加法):110
<p>拼接操作(加法):{{ s|add:msg }}</p> # 拼接操作(加法):hello, my name is yang and my age is 18
# 转义
"""前端"""
<p>转义(html):{{ h5|safe }}</p> # safe表示告诉浏览器是安全的,可以转义
<p>转义(js):{{ js|safe }}</p> # js代码会先执行
"""后端"""
from django.utils.safestring import mark_safe
res = mark_safe('<h1>新垣结衣</h1>')
"""前端接收"""
<p>后端直接传过来转义数据:{{ res }}</p>
"""补充"""
# 前端代码不一定非要在html页面中书写,也可以在后端生成然后传递给html页面。
index.html中输出的效果如下。
三、模版语法之标签
-
for循环
我们在index.html中这样进行书写。
{% for foo in li %}
<p>{{ forloop }}</p>
{% endfor %}
我们发现在浏览器中的到这样的数据【我们可以使用这些参数进行一定的操作】。
之后,我们可以这样进行for循环。
{% for foo in li %}
<p>{{ foo }}</p>
{% endfor %}
- if判断
{% if a %}
...
{% elif b %}
...
{% else %}
...
{% endif %}
- for和if混合使用
{% for foo in li %}
{% if forloop.first %}
<p>这是第一次</p>
{% elif forloop.last %}
<p>这是最后一次</p>
{% else %}
<p>{{ foo }}</p>
{% endif %}
{% endfor %}
"""{% empty %} 如果for循环的可迭代对象内部没有元素,则执行"""
{% for foo in list1 %} # list1 = []
{% if forloop.first %}
<p>这是第一次</p>
{% elif forloop.last %}
<p>这是最后一次</p>
{% else %}
<p>{{ foo }}</p>
{% endif %}
{% empty %}
<p>for循环的可迭代对象内部没有元素,根本没法循环</p>
{% endfor %}
效果显示如下。
- 处理字典
# d.keys 模板语法函数自动执行
{% for foo in d.keys %}
<p>{{ foo }}</p>
{% endfor %}
# d.values
{% for foo in d.values %}
<p>{{ foo }}</p>
{% endfor %}
# d.items
{% for foo in d.items %}
<p>{{ foo }}</p>
{% endfor %}
-
with起别名
在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式。
{% with li.2 as beauty %} # 通过索引取值
<p>{{ beauty }}</p>
<p>{{ li.2 }}</p>
{% endwith %}
效果如下。
四、自定义过滤器、标签及inclusion_tag
"""
先三步走
1.在应用下创建一个名字”必须“叫templatetags文件夹
2.在该文件夹内创建“任意”名称的py文件 eg:mytag.py
3.在该py文件内"必须"先书写下面两句话(单词一个都不能错)
from django import template
register = template.Library()
"""
- 自定义过滤器
"""mytag.py"""
# 自定义过滤器(参数最多两个)【如果需要多个参数,可以'111 222'字符,不能是列表】
@register.filter(name='baby')
def my_sum(v1, v2):
return v1 + v2
# 使用
{% load mytag %} # 加载页面
<p>{{ n|baby:666 }}</p>
- 自定义标签
# 自定义标签(参数可以有多个)【类似于自定义函数】
@register.simple_tag(name='plus')
def index(a,b,c,d):
return '%s-%s-%s-%s'%(a,b,c,d)
# 使用
标签多个参数彼此之间空格隔开
<p>{% plus 'yangyi' 123 123 123 %}</p>
- 自定义inclusion_tag
"""
内部原理
1、先定义一个方法
2、在页面上调用该方法,并且可以传值
3、该方法会生成一些数据然后传递给一个html页面
4、之后将渲染好的结果放到调用的位置
"""
"""mytag.py"""
@register.inclusion_tag('left_menu.html')
def left(n):
data = ['第{}项'.format(i) for i in range(n)]
# 第一种
# return {'data':data} # 将data传递给left_menu.html
# 第二种
return locals() # 将data传递给left_menu.html
"""left_menu.html"""
<ul>
{% for foo in data %}
<li>{{ foo }}</li>
{% endfor %}
</ul>
"""使用"""
{% left 5 %}
# 总结:当html页面某一个地方的页面需要传参数才能够动态的渲染出来,并且在多个页面上都需要使用到该局部,那么就考虑将该局部页面做成inclusion_tag形式。
五、模版的继承
我们可以在浏览一些网站的时候观察到,有些网站的整体都是大差不差的,只有一些局部在进行变化。【当然,不使用模板的继承也没有问题,只不过代码过于冗余】
我们先简单建立页面,样式如下。访问地址为127.0.0.1:8000/home/
我们可以在127.0.0.1:8000/reg
和127.0.0.1:8000/login
的html页面中,简单的继承home.html页面,方式如下。
"""reg.html"""
{% extends 'home.html' %}
"""login.html"""
{% extends 'home.html' %}
如此一来,我们会发现访问reg和login的页面和home一样。
如何进行操作呢?我们可以使用block
将要修改的区域进行重命名。。
{% block content %} # 将这块区域重命名为 content
<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>
{% endblock %}
那么我们在reg.html和login.html中这样进行操作即可。
"""reg.html"""
{% extends 'home.html' %}
{% block content %}
<h1 class="text-center">用户注册</h1>
<form action="" method="post">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="password" class="form-control"></p>
<input type="submit" class="btn btn-success btn-block" value="注册">
</form>
{% endblock %}
"""login.html"""
{% extends 'home.html' %}
{% block content %}
<h1 class="text-center">用户登录</h1>
<form action="" method="post">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="password" class="form-control"></p>
<input type="submit" class="btn btn-danger btn-block" value="登录">
</form>
{% endblock %}
即可实现实现下面效果。
同时,一般情况下模版页面上应该至少有三块可以被修改的区域,包括html区域、css区域和js区域。【每一个子页面就都可以有自己独有的css代码 html代码 js代码】,所以我们可以进行优化。
在要被继承的html文件中,事先划分好要被继承的区域。
"""home.html"""
{% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}
"""reg.html"""
{% extends 'home.html' %}
{% block css %}
<style>
body {
background-color: wheat;
}
</style>
{% endblock %}
{% block content %}
<h1 class="text-center">用户注册</h1>
<form action="" method="post">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="password" class="form-control"></p>
<input type="submit" class="btn btn-success btn-block" value="注册">
</form>
{% endblock %}
{% block js %}
<script>
alert('注册页面')
</script>
{% endblock %}
"""login.html"""
{% extends 'home.html' %}
{% block css %}
<style>
body {
background-color: olivedrab;
}
</style>
{% endblock %}
{% block content %}
<h1 class="text-center">用户登录</h1>
<form action="" method="post">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="password" class="form-control"></p>
<input type="submit" class="btn btn-danger btn-block" value="登录">
</form>
{% endblock %}
{% block js %}
<script>
alert('登录页面')
</script>
{% endblock %}
由此可以实现下述效果。
补充:一般情况下,模版的页面上划定的区域越多,那么该模版的扩展性就越高
但是如果太多,那还不如自己直接重写。
六、模版的导入
可以将html文件当作一个模块,将局部html代码写入其中,需要的时候直接导入即可使用。
"""新建一个new.html文件夹,其中存放"""
<h1>这是一个form表单</h1>
# 导入方式
{% include 'wasai.html' %}