目录
- Django 模板
- 模板传值取值
- 后端传值
- HTML取值
- 过滤器
- default
- length
- filesizeformat
- date
- truncatechars
- truncatewords
- safe
- add
- 标签
- 注释标签
- if/else 标签
- for 标签
- forloop内置对象
- {% empty %}
- include 标签
- csrf_token
- 自定义过滤器
- 自定义 inclusion_tag
- 模板继承
- 父模板
- 子模板
- 父模板如何划分区域
- 模板传值取值
Django 模板
模板传值取值
后端传值
- 键值对形式:
{‘name’:value}
- 精准传值,用啥传啥
- 函数:
locals()
locals()
将当前名称空间中所有的变量名全部传递给页面
HTML取值
- 变量相关:
{{变量名}}
- 逻辑相关:
{% 表达式 %}
代码语言:javascript复制在取值的时候需要注意以下几点
* 传递函数名会自动加括号调用,并返回return后的值
* 传递类名会自动加括号调用实例化成对象
* 传递实例化对象名也返回对象,传递 对象.方法 可以获取该的返回值
* 传递类和函数不需要加括号,自动加括号调用,模板语法不支持额外的传参(形参,实参)
* HTML页面取值可以通过点`.`的方式取值,不论是索引还是键值等···
eg:<p>{{ d.hobby.3.username }}</p>
# 索引就是.下标,字典就是.键
代码语言:javascript复制<p>{{ my_int }}</p>
<p>{{ my_float }}</p>
<p>{{ my_list }}</p>
<p>{{ my_tuple }}</p>
<p>{{ my_dict }}</p>
<p>{{ my_set }}</p>
<p>{{ my_bool }}</p>
<p>{{ get_func }}</p>
<p>{{ MyClass }}</p>
<p>{{ obj.get_cls }}</p>
<p>{{ obj.get_self }}</p>
<p>{{ obj.get_static }}</p>
代码语言:javascript复制def func(request):
my_int = 123
my_float = 3.14
my_list = [1, 2, 3, 4]
my_tuple = (1, 2, 3, 4,)
my_dict = {'name': 'Hammer'}
my_set = {1, 2, 3, 4}
my_bool = True
def get_func():
print('from get_func')
return 'get_func'
class MyClass(object):
def get_self(self):
return '绑定给对象的方法'
@classmethod
def get_cls(cls):
return '绑定给类的方法'
@staticmethod
def get_static():
return '静态方法'
obj = MyClass()
return render(request,'func.html',locals())
过滤器
模板语法:{{ 变量名 | 过滤器:可选参数 }}
模板过滤器可以在变量被显示前修改它,过滤器使用管道字符,如下所示:
代码语言:javascript复制{{ name|lower }}
# 过滤器处理后转小写
管道符的作用:一个过滤器管道的输出又可以作为下一个管道的输入
default
在html文件中,default 为变量提供一个默认值,如果views传的变量布尔值为false,则使用指定的默认值,如果为true,就使用views传的变量值;
代码语言:javascript复制from django.shortcuts import render
def func(request):
id = 0
return render(request,'func.html',locals()) # {'id':id}
'''html'''
<p>{{ id|default:'views传的变量布尔值为false用我吧!' }}</p>
length
- 返回对象的长度,适用于字符串和列表
- 字典返回的是键值对的数量,集合返回的是去重后的长度
字符串:{{ my_str|length }}
列表:{{ my_list|length }}
字典:{{ my_dict|length }}
集合:{{ my_set|length }}
代码语言:javascript复制def func(request):
my_str = 'HammerZe'
my_list = [1, 2, 3, 4]
my_dict = {'name': 'HammerZe', 'age': 18}
my_set = {1, 1, 2, 2, 3, 3, 4, 4}
return render(request, 'func.html', locals())
filesizeformat
以更易读的方式显示文件的大小(即'13 KB', '4.1 MB', '102 bytes'等)
字典返回的是键值对的数量,集合返回的是去重后的长度
代码语言:javascript复制def func(request):
file_data = 1024*1024
return render(request, 'func.html', locals())
代码语言:javascript复制文件大小:{{ file_data|filesizeformat }}
date
根据给定格式对一个日期变量进行格式化。
格式 Y-m-d H:i:s返回 年-月-日 小时:分钟:秒 的格式时间
代码语言:javascript复制def func(request):
import datetime
ctime = datetime.datetime.now()
return render(request, 'func.html', locals())
代码语言:javascript复制时间:{{ ctime|date:'Y-m-d H:i:s' }}
truncatechars
如果字符串包含的字符总个数多于指定的字符数量,那么会被截断掉后面的部分
截断的字符串将以 ... 结尾,...
也算三个字符,比如博客园首页示例
def func(request):
trun_str = 'HammerZe真帅'
return render(request, 'func.html', locals())
代码语言:javascript复制字符串截取:{{ trun_str|truncatechars:9 }}
truncatewords
该过滤器和truncatechars
类似,但是...
不计入长度,空格为分隔符,一个单词为一个单元字符
from django.shortcuts import render
def func(request):
trun_str = 'HammerZe Hans He'
return render(request, 'func.html', locals())
代码语言:javascript复制字符串截取:{{ trun_str|truncatewords:2 }}
safe
将字符串标记为安全,不需要转义。
前端:要保证 views.py 传过来的数据绝对安全,才能用 safe。
后端: 使用views.py 的 mark_safe 效果相同
Django 会自动对 views.py 传到HTML文件中的标签语法进行转义,令其语义失效。加 safe 过滤器是告诉 Django 该数据是安全的,不必对其进行转义,可以让该数据语义生效(这里涉及到xss攻击自行查阅)
代码语言:javascript复制from django.shortcuts import render
def func(request):
unsafe_str = '<h1>不转义,语义失效,携带标签</h1>'
safe_str = '<h1>转义,语义生效,我是一级标题</h1>'
# 后端取消转义
from django.utils.safestring import mark_safe
safe_str1 = mark_safe('<h1>后端取消转义</h1>')
return render(request, 'func.html', locals())
代码语言:javascript复制{{ unsafe_str }}
{{ safe_str|safe }}
{{ safe_str1 }}
add
整型做加法运算,字符串做拼接
代码语言:javascript复制from django.shortcuts import render
def func(request):
add_num = 100
join_str = 'Hammer'
return render(request, 'func.html', locals())
代码语言:javascript复制<p>加法运算:{{ add_num|add:100 }}</p>
<p>字符串拼接:{{ join_str|add:'Ze' }}</p>
标签
注释标签
Django 注释使用 {# #}
代码语言:javascript复制{# 这是一个注释 #}
if/else 标签
- 语法格式:
{% if condition %}
... display
{% endif %}
或者
{% if condition1 %}
... display 1
{% elif condition2 %}
... display 2
{% else %}
... display 3
{% endif %}
# 示例
{% if my_str %}
{{ my_str }}
{% endif %}
def func(request):
my_str = 'HammerZe'
return render(request, 'func.html', locals())
# 页面返回:HammerZe
{% if %} 标签接受 and , or 或者 not 关键字来对多个变量做判断 ,或者对变量取反( not ),例如:
代码语言:javascript复制{% if a and b %}
a 和 b 变量都是可用的。
{% endif %}
for 标签
每一次循环中,模板系统会渲染在 {% for %} 和 {% endfor %} 之间的所有内容;
模板语法for循环和python 的for循环类似,支持in
from django.shortcuts import render
def func(request):
l = [1,2,3,4]
return render(request, 'func.html', locals())
{% for foo in l %}
{{ foo }}
{% endfor %}
给标签增加一个 reversed
使得该列表被反向迭代
{% for foo in l reversed %}
{{ foo }}
{% endfor %}
遍历字典: 可以直接用字典 .items 方法,用变量的解包分别获取键和值
代码语言:javascript复制from django.shortcuts import render
def func(request):
my_dict = {'name': 'HammerZe', 'age': 18, 'gender': 'male'}
return render(request, 'func.html', locals())
代码语言:javascript复制# 分别获取k,v
{% for k in my_dict %}
{{ k }}
{#{{ v }}#}
{% endfor %}
代码语言:javascript复制# 获取k,v
{% for k,v in my_dict.items %}
{{ k }}
{{ v }}
{% endfor %}
forloop内置对象
代码语言:javascript复制{% for k in my_dict %}
{{ forloop }}
{% endfor %}
在 {% for %} 标签里可以通过 {{forloop}} 变量获取循环序号。
- forloop.counter: 顺序获取循环序号,从 1 开始计算
- forloop.counter0: 顺序获取循环序号,从 0 开始计算
- forloop.revcounter: 倒序获取循环序号,结尾序号为 1
- forloop.revcounter0: 倒序获取循环序号,结尾序号为 0
- forloop.first(一般配合if标签使用): 第一条数据返回 True,其他数据返回 False
- forloop.last(一般配合if标签使用): 最后一条数据返回 True,其他数据返回 False
{% for i in views_list %}
{#<p>{{ forloop.counter }}</p>#} # 1 2 3 4 5
{#<p>{{ forloop.counter0 }}</p>#} # 0 1 2 3 4
{#<p>{{ forloop.revcounter }}</p>#} # 5 4 3 2 1
{#<p>{{ forloop.revcounter0 }}</p>#} # 4 3 2 1 0
<p>{{ forloop.first }}</p> # True False False False False
<p>{{ forloop.last }}</p> # False False False False True
{% endfor %}
from django.shortcuts import render
def func(request):
views_list = ["a", "b", "c", "d", "e"]
return render(request, 'func.html', locals())
{% empty %}
代码语言:javascript复制{% empty %} 从句:在循环为空的时候执行(即 in 后面的参数布尔值为 False )
{% for i in views_list %}}}
{{ i }}
{% empty %}
空列表当然执行~
{% endfor %}
include 标签
{% include %} 标签允许在模板中包含其它的模板的内容,类似后端导入模块
代码语言:javascript复制{% include 'func2.html'%}
# func2.html
<h1>哈哈哈</h1>
csrf_token
作用:跨站请求伪造保护。
在我们使用form表单的时候,经常报403权限错误,这里我们可以在HTML页面使用
{% csrf_token %}
,表单提交数据才会成功,或者在settings.py将中间件注释掉也可以;
解析:
首先,向服务器发送请求,获取登录页面,此时中间件 csrf 会自动生成一个隐藏input标签,该标签里的 value 属性的值是一个随机的字符串,用户获取到登录页面的同时也获取到了这个隐藏的input标签。
然后,等用户需要用到form表单提交数据的时候,会携带这个 input 标签一起提交给中间件 csrf,原因是 form 表单提交数据时,会包括所有的 input 标签,中间件 csrf 接收到数据时,会判断,这个随机字符串是不是第一次它发给用户的那个,如果是,则数据提交成功,如果不是,则返回403权限错误。
自定义过滤器
1、在应用目录下创建 templatetags 目录名只能是 templatetags;
2、在 templatetags 目录下创建任意 py 文件,如:my_tag.py。
3、my_tag.py 文件代码如下:
代码语言:javascript复制from django import template
register = template.Library() #register的名字是固定的,不可改变
4、利用装饰器 @register.filter
自定义过滤器
注意:自定义过滤器也只能接收两个参数,因为|
本质就是前面的参数交给后面过滤器处理,过滤器最强多可自带一个参数
'''my_tag.py'''
# 自定义过滤器
@register.filter(name='myfilter')
def index(x,y):
return x * y
'''views.py'''
from django.shortcuts import render
def func(request):
a=10
return render(request, 'func.html', locals())
代码语言:javascript复制{#加载过滤器#}
{% load my_tag %}
{#使用过滤器#}
{{ a|myfilter:10 }}
5、自定义标签
代码语言:javascript复制@register.simple_tag(name='mytag')
def tag(x, y, z): # 自定义标签可以接收n个参数
return x y z
代码语言:javascript复制{#加载过滤器#}
{% load my_tag %}
{% mytag 1 2 3 %}
自定义 inclusion_tag
类似将html页面功能分块返回了~
自定义inclusion_tag,my_tag.py
代码语言:javascript复制from django import template
register = template.Library() # register的名字是固定的,不可改变
@register.inclusion_tag('login.html',name='my_inclusion')
def inclusion(n):
l = []
for i in range(1,n):
l.append(f'第{i}页')
return locals() # 将当前名称空间所有名字返回给login.html
views.py
代码语言:javascript复制def func(request):
return render(request, 'func.html', locals())
lit.py 中间html
代码语言:javascript复制<ul>
{% for foo in l %}
<li>{{ foo}}</li>
{% endfor %}
</ul>
func.html
代码语言:javascript复制{#加载过滤器#}
{% load my_tag %}
{#生成10个li#}
{% my_inclusion 10 %}
模板继承
模板可以用继承的方式来实现复用,减少冗余内容。
网页的头部和尾部内容一般都是一致的,我们就可以通过模板继承来实现复用。
父模板用于放置可重复利用的内容,子模板继承父模板的内容,并放置自己的内容。
父模板
标签 block...endblock: 父模板中的预留区域,该区域留给子模板填充差异性的内容,不同预留区域名字不能相同
代码语言:javascript复制{% block 名称 %}
预留给子模板的区域,可以设置设置默认内容
{% endblock 名称 %}
子模板
子模板使用标签 extends 继承父模板:
代码语言:javascript复制{% extends "父模板路径"%}
子模板如果没有设置父模板预留区域的内容,则使用在父模板设置的默认内容,当然也可以都不设置,就为空。
子模板设置父模板预留区域的内容:
代码语言:javascript复制{% block 名称 %}
子内容
{% endblock 名称 %}
子版也可以继续使用母版划定区域内的内容
代码语言:javascript复制{{ block.super }}
父模板如何划分区域
划定区域的时候一般都应该有三个区域:CSS区域,HTML文档区域、JS区域
这样划分区域提高了页面的可扩展性和方便维护等优点
代码语言:javascript复制 {% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}