模版语法
目录
记忆小技巧
前端接收后端数据的两种方式
- {{}} ---- 变量相关
- {%%} ---- 逻辑相关
模版语法可以传递的后端python数据类型
基本数据类型
- views.py
def index(request):
my_str = '鬼鬼'
my_int = 11
my_list = [1,2,3]
my_tup = (1,2,3)
my_dic = {'name':'鬼鬼','age':18}
my_set = {1,3,4}
my_bool = True
my_float = 11.11
return render(request,'data.html',locals())
- data.html
{{ my_int }}
{{ my_float }}
{{ my_str }}
{{ my_list }}
{{ my_tup }}
{{ my_dic }}
{{ my_bool }}
{{ my_set }}
对象传值
- views.py
from django.shortcuts import render
# Create your views here.
def index(request):
def func():
print('我是func')
return 'func'
class Class():
def get_self(self):
return 'self'
@staticmethod
def static():
return 'static'
@classmethod
def class_method(cls):
return cls
# 打印类/对象是自动触发,代替对象的内存地址
def __str__(self):
return '我是谁?'
obj = Class()
return render(request,'data.html',locals())
- data.html
{{ func }}
<p>传递函数名,就会将后端的函数自动加括号调用,得到该函数的返回值,但是模板语法不支持给函数传参数</p>
<p>传类名的时候也会自动加括号调用,即实例化</p>
<p>模版语法内部能够自动判断出当前的变量名是否可以加括号调用,如果可以就会自动执行,针对的是函数名和类名</p>
<p>{{ Class }}</p>
<p>{{ obj }}</p>
<p>{{ obj.get_self }}</p>
<p>{{ obj.static }}</p>
<p>{{ obj.class_method}}</p>
前端模版语法取值
django模版语法的取值都是固定的格式,只能采用‘句点符’,即值可以通过索引或者键点
出来
<p>{{ my_str.0 }}</p>
<p>{{ my_list.1 }}</p>
<p>{{ my_dic.name }}</p>
过滤器
简介
- 过滤器最多只能有两个参数
- 过滤器就类似于是模版语法内置的内置方法,与后端数据类型的内置方法类似
- django内置有60多个过滤器
过滤器的基本语法
{{数据|过滤器:参数}}
过滤器的基本使用
<p>统计长度{{ my_str|length }}</p>
<p>默认值,如果布尔值是True,默认值就是True,否则展示冒号后面的值{{ my_bool|default:'啥也不是' }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>日期格式化:{{ current_time|date:'Y-m-d H:i:s' }}</p>
<p>切片操作,支持步长,顾头不顾尾{{ my_list|slice:'0:2:1' }}</p>
<p>摘要操作包含三个点(案例博客园的摘要){{ info|truncatechars:9 }}</p>
<p>切取单词,不包含三个点,只会按照空格切分单词{{ egn|truncatewords:'9' }}</p>
<p>移除特定的字符{{ msg|cut:' ' }}</p>
<p>拼接操作{{ my_str|join:'@' }}</p>
<p>加法运算(拼接操作){{ my_int|add:12 }}</p>
<p>加法运算(拼接操作){{ my_str|add:'12' }}</p>
过滤器的高级使用 --- 转义
在写全栈项目的时候,前端代码不一定非要在前端页面书写,也可以在后端写好,然后传递给前端
- 前端将后端带有标签的字符串转为前端代码
- 后端代码
h = '<h1>我是html标签</h1>'
- 前端转义,过滤器的意思是告诉浏览器后端写的标签是安全的,可以进行渲染
{{h|safe}}
- 后端直接将带有标签的字符串转为前端代码,然后前端直接通过模版语法拿来用即可
- 后端
from django.utils.safestring import mark_safe
s = '<h1>后端转义</h1>'
res = mark_safe(s)
- 前端
{{res}}
标签 --- 就是一堆逻辑
前端页面for循环
forloop
{% for foo in my_list %}
<p>{{ forloop }}</p>
{% endfor %}
--------------------------------------
// 产生的结果
{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 7, 'revcounter0': 6, 'first': True, 'last': False}
{'parentloop': {}, 'counter0': 1, 'counter': 2, 'revcounter': 6, 'revcounter0': 5, 'first': False, 'last': False}
{'parentloop': {}, 'counter0': 2, 'counter': 3, 'revcounter': 5, 'revcounter0': 4, 'first': False, 'last': False}
{'parentloop': {}, 'counter0': 3, 'counter': 4, 'revcounter': 4, 'revcounter0': 3, 'first': False, 'last': False}
{'parentloop': {}, 'counter0': 4, 'counter': 5, 'revcounter': 3, 'revcounter0': 2, 'first': False, 'last': False}
{'parentloop': {}, 'counter0': 5, 'counter': 6, 'revcounter': 2, 'revcounter0': 1, 'first': False, 'last': False}
{'parentloop': {}, 'counter0': 6, 'counter': 7, 'revcounter': 1, 'revcounter0': 0, 'first': False, 'last': True}
// 需要知道的:
first:标识当前是否是第一次循环
last:标识当前是否是最后一次循环
counter0:类似于列表的索引
couter:正常从1开始的第几个元素
for循环
{% for foo in my_list %} <!--等价于for i in my_list-->
<p>{{ foo}}</p>
{% endfor %}
- for循环处理字典的方法 ---- 与python后端非常类似
{% for foo in my_dic.keys %}
<p>{{ foo }}</p>
{% endfor %}
{% for foo in my_dic.values %}
<p>{{ foo }}</p>
{% endfor %}
{% for foo in my_dic.items %}
<p>{{ foo }}</p>
{% endfor %}
if判断
{% if my_bool %}
<p>love</p>
{% elif s %}
<p>哈哈</p>
{% else %}
<p>呼哈呼哈</p>
{% endif %}
for与if混合使用
{% for foo in my_list %}
{% if forloop.first %}
<p>first</p>
{% elif forloop.last %}
<p>last</p>
{% else %}
<p>{{ foo }}</p>
{% endif %}
{% empty %}
<p>如果for循环的可迭代对象内部没有元素,无法开始循环时就执行</p>
{% endfor %}
with起别名
在with语法内可以通过as后面的别名快速的使用到前面非常负责的获得数据的方式所得到的数据
{% with d.hobby.3.info as nb %}
<p>{{ nb }}</p>
在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式
<p>{{ d.hobby.3.info }}</p>
{% endwith %}
自定义过滤器 标签 inclusion_tag
自定义过滤器 标签 inclusion_tag的三个必须步骤
- 在应用下创建一个名字必须叫templatetags的文件夹
- 在该文件夹内创建任意名称的py文件
- 在该py文件内必须先书写下面两句话
from django import template
register = template.Library()
自定义过滤器
自定义过滤器
- templatetags.mytag.py
from django import template
register = template.Library()
@register.filter(name='my_filter') # name=自定义过滤器的名字
# 过滤器的功能
def my_sum(v1, v2):
return v1 + v2
# 注意:自定义过滤器最多只能接收两个参数
自定义过滤器的使用
- data.html
{% load mytag %}
<p>{{ my_int|love:12 }}</p>
</body>
// 用法与内置过滤器相同,只是在使用自定义过滤器之前需要在页面加载过滤器所在的py文件{% load mytag %}
自定义标签
自定义标签
- templatetags.mytag.py
from django import template
register = template.Library()
# 自定义标签,参数可以有多个
@register.simple_tag(name='my_tag') # name=自定义标签的名字
def index(a,b,c):
return f'{a}{b}{c}'
自定义标签的使用
<p>{% my_tag 'h' 'e' 'o' %}</p>
// 自定义标签的使用,第一句话还是加载自定义标签所在的py文件{% load mytag %},如果页面上已经加载过了,就无需进行第二次加载
// 标签多个参数彼此之间空格隔开,语法{% 标签名字 参数1 参数2 参数3 %}
自定义inclusion_tag
内部原理
- 先定义一个方法
- 在html页面上调用该方法,并且可以传值
- 该方法会生成一些数据然后传递给另一个html页面
- 之后将渲染后的结果第二个html页面放到第一个html页面调用inclusion_tag的位置
使用场景
当html页面某一个地方的页面需要传参数才能够动态的渲染出来,并且在多个页面上都需要使用到该局部 那么就考虑将该局部页面做成inclusion_tag形式
自定义inclusion_tag
- templatetags.mytag.py
@register.inclusion_tag('left_menu.html')
def left(n):
data = ['第{}项'.format(i) for i in range(n)]
'''
第一种传值的方式
return {'data':data}
'''
# 第二种传值的方式
return locals() # 将data传值给left_menu.html
- left_menu.html(自定义inclusion_tag渲染页面)
<ul>
{% for foo in data %}
<li>{{ foo }}</li>
{% endfor %}
</ul>
// 这个页面是html页面的局部,因此需要将页面清空
- data.html(调用inclusion_tag的页面)
{% left 10 %} // {% 自定义inclusion_tag的函数名 参数%}
// 第一句话还是加载自定义标签所在的py文件{% load mytag %},如果页面上已经加载过了,就无需进行第二次加载
模板的继承
简介
- 具体案例:某些网站的页面只是一些局部在做变化,其他位置不做任何改变
模板的继承实现上述案例
- 第一步:选好一个想要继承的页面 ---- 模板页面
- 第二步:在继承模板页面的html文档中清空所有内容,因为这个页面不是整体的页面,而是局部的一块---称为子页面,在子页面上首先书写下列代码
{% extends '模板页面的文件名' %}
# 这行代码的意思就是继承了模板页面上的所有的内容
- 第三步:需要在模板页面上提前划定可以被修改的区域,在模板页面上划定可以被修改区域的方式就是在可以被修改的代码外层包裹下述代码
{% block content %} // content是可以被修改部分的名字,可以是任意的
可以被修改的部分
{% endblock%}
- 第四步:在子页面上声明想要修改模板页面上划定了的区域
{% block content %} // content是可以被修改部分的名字,可以是任意的
子页面独有的内容
{% endblock%}
- 模板的继承需要知道的知识
一般情况下模板页面应该至少有三块可以被修改的区域
- css区域 放在head标签内
- html区域
- js区域 放在页面最下部分
{% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}
这样每一个子页面就可以有自己独有的js和css代码
需要注意的是:一般情况下 模版的页面上划定的区域越多 那么该模版的扩展性就越高
但是如果太多 那还不如自己直接写
模板的导入
简介
将某一个页面(局部页面)当成模块的形式,哪个地方需要直接导入即可
语法格式
{% include '被导入页面的名字 '%}
# 例如{% include 'wasai.html' %}