模板-变量、过滤器、 标签
一、变量
在Django模板中便利复杂数据结构的关键是据点字符,语法: {{变量名}}
views.py
def template_test(request):
name = 'lqz'
li = ['lqz', 1, '18']
dic = {'name': 'lqz', 'age': 18}
ll2 = [
{'name': 'lqz', 'age': 18},
{'name': 'lqz2', 'age': 19},
{'name': 'egon', 'age': 20},
{'name': 'kevin', 'age': 23}
]
ll3=[]
class Person:
def __init__(self, name):
self.name = name
def test(self):
print('test函数')
return 11
@classmethod
def test_classmethod(cls):
print('类方法')
return '类方法'
@staticmethod
def static_method():
print('静态方法')
return '静态方法'
lqz = Person('lqz')
egon = Person('egon')
person_list = [lqz, egon]
bo = True
te = test()
import datetime
now=datetime.datetime.now()
link1='<a href="https://www.baidu.com">点我<a>'
from django.utils import safestring
link=safestring.mark_safe(link1)
# html特殊符号对照表(http://tool.chinaz.com/Tools/htmlchar.aspx)
# 这样传到前台不会变成特殊字符,因为django给处理了
dot='♠'
# return render(request, 'template_index.html', {'name':name,'person_list':person_list})
return render(request, 'template_index.html', locals())
html
<p>{{ name }}</p>
<p>{{ li }}</p>
<p>{{ dic }}</p>
<p>{{ lqz }}</p>
<p>{{ person_list }}</p>
<p>{{ bo }}</p>
<p>{{ te }}</p>
<hr>
<h3>深度查询句点符</h3>
<p>{{ li.1 }}</p>
<p>{{ dic.name }}</p>
<p>{{ lqz.test }}</p>
<p>{{ lqz.name }}</p>
<p>{{ person_list.0 }}</p>
<p>{{ person_list.1.name }}</p>
<hr>
<h3>过滤器</h3>
{#注意:冒号后面不能加空格#}
<p>{{ now | date:"Y-m-d H:i:s" }}</p>
{#如果变量为空,设置默认值,空数据,None,变量不存在,都适用#}
<p>{{ name |default:'数据为空' }}</p>
{#计算长度,只有一个参数#}
<p>{{ person_list |length }}</p>
{#计算文件大小#}
<p>{{ 1024 |filesizeformat }}</p>
{#字符串切片,前闭后开,前面取到,后面取不到#}
<p>{{ 'hello world lqz' |slice:"2:-1" }}</p>
<p>{{ 'hello world lqz' |slice:"2:5" }}</p>
{#截断字符,至少三个起步,因为会有三个省略号(传负数,1,2,3都是三个省略号)#}
<p>{{ '刘清政 world lqz' |truncatechars:"4" }}</p>
{#截断文字,以空格做区分,这个不算省略号#}
<p>{{ '刘清政 是 大帅比 谢谢' |truncatewords:"1" }}</p>
<p>{{ link1 }}</p>
<p>{{ link1|safe }}</p>
<p>{{ link }}</p>
<p>♠</p>
<p>{{ dot }}</p>
{#add 可以加负数,传数字字符串都可以#}
<p>{{ "10"|add:"-2" }}</p>
<p>{{ li.1|add:"-2" }}</p>
<p>{{ li.1|add:2 }}</p>
<p>{{ li.1|add:"2" }}</p>
<p>{{ li.1|add:"-2e" }}</p>
{#upper#}
<p>{{ name|upper }}</p>
<p>{{ 'LQZ'|lower }}</p>
<hr>
<h3>模版语法之标签</h3>
{#for 循环 循环列表,循环字典,循环列表对象#}
<ui>
{% for foo in dic %}
{{ foo }}
{% endfor %}
{#也可以混用html标签#}
{% for foo in li %}
<ul>foo</ul>
{% endfor %}
</ui>
{#表格#}
<table border="1">
{% for foo in ll2 %}
<tr>
<td>{{ foo.name }}</td>
<td>{{ foo.age }}</td>
</tr>
{% endfor %}
</table>
<table border="1">
{#'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}#}
{% for foo in ll2 %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ foo.name }}</td>
<td>{{ foo.age }}</td>
</tr>
{% endfor %}
</table>
{% for foo in ll5 %}
<p>foo.name</p>
{% empty %}
<p>空的</p>
{% endfor %}
<hr>
<h3>if判断</h3>
{% if name %}
<a href="">hi {{ name }}</a>
<a href="">注销</a>
{% else %}
<a href="">请登录</a>
<a href="">注册</a>
{% endif %}
{#还有elif#}
<hr>
<h3>with</h3>
{% with ll2.0.name as n %}
{{ n }}
{% endwith %}
{{ n }}
{% load my_tag_filter %}
{{ 3|multi_filter:3 }}
{#传参必须用空格区分#}
{% multi_tag 3 9 10 %}
{#可以跟if连用#}
{% if 3|multi_filter:3 > 9 %}
<p>大于</p>
{% else %}
<p>小于</p>
{% endif %}
注意:句点符也可以用来引用对象的方法(无参数方法):
<h4>字典:{{ dic.name.upper }}<``/``h4>
课上:
'''
def dtl(request):
num = 3.14
ss = 'abc123嘿嘿'
# return render(request, 'django_dtl.html', {'number': num, 'ss': ss})
result = True
list = [1, 2, 3, 4, 5]
dic = {'name': 'owen', 'age': 28}
# 函数不能带有参数,模板中{{ fn }} 本质就是调用函数拿到函数值(函数的返回值)
def fn():
return "fn function"
class Person:
name = "name"
def __str__(self):
return "这是Person类"
p = Person()
# locals()存放当前作用域中所有的名字
return render(request, 'django_dtl.html', locals())
'''
'''
<li>{{ num }}</li>
<li>{{ list }} -- {{ list.0 }}</li>
<li>{{ dic }} -- {{ dic.age }}</li>
<li>{{ Person }}</li> # Person() => __str__的返回值
<li>{{ 123 }}</li> # 也可以直接写数字、字符串、布尔值
'''
二、过滤器
语法:
{{ 变量|过滤器1[[:参数]|...|过滤器n[:参数]] }}
注:过滤器可以串联操作,可以拥有0个或1个参数
常见内置filter
-- 增加 add:num
-- 字符串长度 length
-- 默认值 default:'默认值' # 变量不存在或为空
-- 全大写 upper
-- 全小写 lower
-- 切片 slice:'0:-1'
-- 将数字转换为文件大小 filesizeformat
-- 字符串隐藏 truncatechars:13 # 只显示10个字符,后置字符都用...来替代
-- 时间 date:'Y-m-d'
-- 转换原意 safe
default:
如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如
{{ value|default:"nothing" }}
length:
返回值的长度。它对字符串和列表都起作用。例如:
{{ value|length }}
如果 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。
filrsizeformat:
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:
{{ value|filesizeformat }}
如果 value 是 123456789,输出将会是 117.7 MB
date:
如果 value=datetime.datetime.now()
{{ value|date:"Y-m-d" }}
slice:
如果 value="hello world"
{{ value|slice:"2:-1" }}
truncatecharss:
如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:要截断的字符数
例如:
{{ value|truncatechars:9 }}
safe:
Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。比如:
value``=``"<a href="``">点击</a>"
{{ value|safe}}
其他过滤器(了解):
过滤器 | 描述 | 示例 |
---|---|---|
upper | 以大写方式输出 | {{ user.name | upper }} |
add | 给value加上一个数值 | {{ user.age | add:”5” }} |
addslashes | 单引号加上转义号 | |
capfirst | 第一个字母大写 | {{ ‘good’| capfirst }} 返回”Good” |
center | 输出指定长度的字符串,把变量居中 | {{ “abcd”| center:”50” }} |
cut | 删除指定字符串 | {{ “You are not a Englishman” | cut:”not” }} |
date | 格式化日期 | |
default | 如果值不存在,则使用默认值代替 | {{ value | default:”(N/A)” }} |
default_if_none | 如果值为None, 则使用默认值代替 | |
dictsort | 按某字段排序,变量必须是一个dictionary | {% for moment in moments | dictsort:”id” %} |
dictsortreversed | 按某字段倒序排序,变量必须是dictionary | |
divisibleby | 判断是否可以被数字整除 | {{ 224 | divisibleby:2 }} 返回 True |
escape | 按HTML转义,比如将”<”转换为”<” | |
filesizeformat | 增加数字的可读性,转换结果为13KB,89MB,3Bytes等 | {{ 1024 | filesizeformat }} 返回 1.0KB |
first | 返回列表的第1个元素,变量必须是一个列表 | |
floatformat | 转换为指定精度的小数,默认保留1位小数 | {{ 3.1415926 | floatformat:3 }} 返回 3.142 四舍五入 |
get_digit | 从个位数开始截取指定位置的数字 | {{ 123456 | get_digit:’1’}} |
join | 用指定分隔符连接列表 | {{ [‘abc’,’45’] | join:’’ }} 返回 abc45 |
length | 返回列表中元素的个数或字符串长度 | |
length_is | 检查列表,字符串长度是否符合指定的值 | {{ ‘hello’| length_is:’3’ }} |
linebreaks | 用 或 |
{{ “Hi
David”|linebreaks }} 返回 Hi David |
linebreaksbr | 用 标签代替换行符 |
|
linenumbers | 为变量中的每一行加上行号 | |
ljust | 输出指定长度的字符串,变量左对齐 | {{‘ab’|ljust:5}}返回 ‘ab ’ |
lower | 字符串变小写 | |
make_list | 将字符串转换为列表 | |
pluralize | 根据数字确定是否输出英文复数符号 | |
random | 返回列表的随机一项 | |
removetags | 删除字符串中指定的HTML标记 | {{value | removetags: “h1 h2”}} |
rjust | 输出指定长度的字符串,变量右对齐 | |
slice | 切片操作, 返回列表 | {{[3,9,1] | slice:’:2’}} 返回 [3,9] {{ 'asdikfjhihgie' | slice:':5' }} 返回 ‘asdik’ |
slugify | 在字符串中留下减号和下划线,其它符号删除,空格用减号替换 | {{ '5-2=3and5 2=3' | slugify }} 返回 5-23and5-23 |
stringformat | 字符串格式化,语法同python | |
time | 返回日期的时间部分 | |
timesince | 以“到现在为止过了多长时间”显示时间变量 | 结果可能为 45days, 3 hours |
timeuntil | 以“从现在开始到时间变量”还有多长时间显示时间变量 | |
title | 每个单词首字母大写 | |
truncatewords | 将字符串转换为省略表达方式 | {{ 'This is a pen' | truncatewords:2 }} 返回This is ... |
truncatewords_html | 同上,但保留其中的HTML标签 | {{ ' This is a pen ' | truncatewords:2 }}返回This is ... |
urlencode | 将字符串中的特殊字符转换为url兼容表达方式 | {{ ‘http://www.aaa.com/foo?a=b&b=c’ | urlencode}} |
urlize | 将变量字符串中的url由纯文本变为链接 | |
wordcount | 返回变量字符串中的单词数 | |
yesno | 将布尔变量转换为字符串yes, no 或maybe | {{ True | yesno }}{{ False | yesno }}{{ None | yesno }} 返回 yes no maybe |
三、标签
标签看起来像是这样的: {% tag %}。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})。
语法:
-- {% 关键词 arg1 ... argn %} eg: {% url 'test' 1 2 3 %} => /test/1/2/3/
2.常用:
-- 反向解析url {% url 'namespace:url_name' arg1 arg2 %}
-- 当前时间now {% now 'Y-m-d' %}
-- 起别名with {% with '后面的别名flag就代表我' as flag %} {{ flag }} {% endwith %}
-- Django CSRF认证 {% csrf_token %}
eg:
<ul>
<li>{% url 'test' 1 2 3 %}</li>
<li>
{# 起别名 #}
{% with link|safe as lk %}
{{ lk }}
{{ lk }}
{{ lk }}
{% endwith %}
{% with n='123456789' %}
{{ n }}
{{ n }}
{{ n }}
{% endwith %}
</li>
<li>
{% now 'Y-m-d' %}
</li>
<li>
{# <form action="" method="post">#}
{# 该页面为Django自身渲染, 渲染时告诉页面自身的认证条件,该页面发送post请求都可以通过认证 #}
{# {% csrf_token %}#}
{# <input type="submit">#}
{# </form>#}
</li>
<li>
{% with 10|add:0 as num %}
{% if num|add:0 > 10 %}
<p>num值大于10</p>
{% elif num|add:0 == 10 %}
<p>num值等于10</p>
{% else %}
{% if num|add:0 > 5 %}
<p>num介于5与10</p>
{% else %}
<p>num不大于5</p>
{% endif %}
{% endif %}
{% endwith %}
</li>
<li>
{% for n in 31425|make_list %}
<p>{{ forloop }}</p>
<p>第{{ forloop.counter }}次迭代</p>
<p>{{ n }}</p>
<hr>
{% endfor %}
</li>
<li>
{% for l in ll %}
{# <p>{{ foo }}</p>#}
{# <hr>#}
{# <p>外层第{{ forloop.counter }}循环</p>#}
{% for n in l %}
{# <p>内层第{{ forloop.counter }}循环</p>#}
<p>外层{{ forloop.parentloop.counter }} - 内层{{ forloop.counter }}</p>
{{ n }}
<hr>
{% endfor %}
{% empty %}
<p>迭代的ll不存在或为空</p>
{% endfor %}
</li>
</ul>
for标签
遍历每一个元素:
{% for person in person_list %}
<p>{{ person.name }}</p>
{% endfor %}
可以利用{% for obj in list reversed %}反向完成循环。
遍历一个字典:
{% for key,val in dic.items %}
<p>{{ key }}:{{ val }}</p>
{% endfor %}
注:循环序号可以通过{{forloop}}显示
forloop.counter The current iteration of the loop (1-indexed) 当前循环的索引值(从1开始)
forloop.counter0 The current iteration of the loop (0-indexed) 当前循环的索引值(从0开始)
forloop.revcounter The number of iterations from the end of the loop (1-indexed) 当前循环的倒序索引值(从1开始)
forloop.revcounter0 The number of iterations from the end of the loop (0-indexed) 当前循环的倒序索引值(从0开始)
forloop.first True if this is the first time through the loop 当前循环是不是第一次循环(布尔值)
forloop.last True if this is the last time through the loop 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环
迭代器
{% for foo in iterate %}
{{ forloop }}
{% empty %}
可迭代对象为空
{% endfor %}
注:
1. iterate为可迭代对象
2. iterate可以添加filter
3. forloop变量为存放迭代信息的字典,父级forloop字典,开始索引从0编号或1编号,倒序索引从0编号或1编号,是否是第一次或最后一次循环
4. empty分支会在可迭代对象不存在或空时执行
for .. empty
for标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。
{% for person in person_list %}
<p>{{ person.name }}</p>
{% empty %}
<p>sorry,no person here</p>
{% endfor %}
if 标签--------分支
{% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。
{% if num > 100 or num < 0 %}
<p>无效</p>
{% elif num > 80 and num < 100 %}
<p>优秀</p>
{% else %}
<p>凑活吧</p>
{% endif %}
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
with
使用一个简单地名字缓存一个复杂的变量,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的
例如:
{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}
不要写成as
csrf_token
{% csrf_token%}
这个标签用于跨站请求伪造保护
四、自定义过滤器与标签
'''
步骤:
1. 在注册的app下创建templatetags包
2. 在模板中自定义模块py文件,如:owen_tags.py
3. 要在使用自定义filter与tag的模板页面中加载自定义模块py文件,案例:{% load owen_tags %}
4. 自定义filter语法
from django.template import Library
register = Library()
@register.filter(name='jump')
def owen_jump(value, arg):
try:
return value * int(arg)
except (ValueError, TypeError):
return ''
5. 自定义tag语法
@register.simple_tag(name='add_two')
def owen_add(arg1, arg2):
try:
return int(arg1) + int(arg2)
except (ValueError, TypeError):
try:
return arg1 + arg2
except Exception:
return ''
6. 在加载了自定义模块py文件的模板页面中使用,案例:
{{ 10|jump:2}} # 10 * 2
{% add_two 10 20 %} # 10 + 20
'''
参考:https://www.cnblogs.com/liuqingzheng/articles/9509806.html#_label1