目录
一、模板概念
二、 模板语法 - 变量 : {{ 变量 }}
1、直接调用输出 - 相当于print
2、深度取值 - 获取对象内部值
三、模板语法 - 过滤器 :{{ 位置参数1 | 过滤器函数 : 位置参数2}}
1- default :如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。
2- length : 返回值的长度。它对字符串和列表都起作用
3- filesizeformat :将值格式化为一个可读性高的文件尺寸
4- date :格式化日期
5- slice:切片操作
6- truncatechars :如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
7- safe :是否转义输入框内的html、js元素等(使用-转义;不使用-不转义)
8- 其他过滤器
四、模板语法 - 标签 : {% tag %} …… {% endtag%}
1- for标签:循环结构
1-1 查看循环信息:{{ forloop }}
1-2 for …… empty :若循环对象为空执行empty内代码块
2、if标签:逻辑判断
3、with 标签: 取别名,简化变量名
4、csrf_token 标签:跨站请求伪造保护 {% csrf_token%}
五、自定义模板语法
1、自定义标签(参数不限,但不能放在if for语句中)- @register.simple_tag
1-1 @register.inclusion_tag --- 返回可迭代对象(qureyset对象)
2、自定义过滤器 - @register.filter
一、模板概念
DTL语言 - Django Template Language
你可能已经注意到我们在例子视图中返回文本的方式有点特别。 也就是说,HTML被直接硬编码在 Python代码之中。
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
尽管这种技术便于解释视图是如何工作的,但直接将HTML硬编码到你的视图里却并不是一个好主意。
对页面设计进行的任何改变都必须对 Python 代码进行相应的修改。 站点设计的修改往往比底层 Python 代码的修改要频繁得多,因此如果可以在不进行 Python 代码修改的情况下变更设计,那将会方便得多。 Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成。 设计者和HTML/CSS的编码人员不应该被要求去编辑Python的代码来完成他们的工作。 程序员编写 Python代码和设计人员制作模板两项工作同时进行的效率是最高的,远胜于让一个人等待另一个人完成对某个既包含 Python又包含 HTML 的文件的编辑工作。
因此,将页面的设计和Python的代码分离开会更干净简洁更容易维护。 我们可以使用 Django的 模板系统 (Template System)来实现这种模式,这就是本章要具体讨论的问题
python的模板:HTML代码+模板语法
# 视图函数 传输数据给模板
def inde_action(request):
# 推荐写法
name = 'name1'
list00 = [1,2,3,'hello','django']
dic = {'name':'name2','age':18}
def test():
print('hello world')
return 'fun-test'
class Person():
pass
# locals()方法可以返回视图函数内所有定义的 变量、函数、类等
return render(request, 'index.html', locals())
二、 模板语法 - 变量 : {{ 变量 }}
1、直接调用输出 - 相当于print
{#模板语言注释:前端看不到#}
{#相当于print了该变量#}
<h1>模板语言之变量</h1>
<p>字符串:{{ name }}</p>
<p>数字:{{ age }}</p>
<p>列表:{{ ll }}</p>
<p>元组:{{ tu }}</p>
<p>字典:{{ dic }}</p>
{#只写函数名:相当于函数名(),执行该函数,显示的是返回值#}
<p>函数:{{ test }}</p>
{#对象调用显示内存地址#}
<p>对象:{{ lqz }}</p>
{# person_list=[p1,p2] #}
<p>列表套对象:{{ person_list }}</p>
{# person_dic={'p1':p1} #}
<p>字典套对象:{{ person_dic }}</p>
2、深度取值 - 获取对象内部值
<h1>深度查询</h1>
{# 一层 #}
<p>列表第0个值:{{ ll.0 }}</p>
<p>列表第4个值:{{ ll.3 }}</p>
<p>字典取值:{{ dic.name }}</p>
<p>字典取列表值:{{ dic.ll }}</p>
{# 二层 #}
<p>对象取数据属性:{{ p1.name }}</p>
<p>对象取绑定给对象的函数属性:{{ p1.get_name }}</p>
<p>对象取绑定给类的函数属性:{{ p1.cls_test }}</p>
<p>对象取静态方法:{{ p1.static_test }}</p>
<p>把对象列表中,其中对象的一个年龄属性取出来:{{ person_list.1.age }}</p>
{# 注意:不能调有参数的方法 #}
<p>字符串的方法:{{ name.upper }}</p>
三、模板语法 - 过滤器 :{{ 位置参数1 | 过滤器函数 : 位置参数2}}
1- default :如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。
{{ value|default:"nothing" }}
2- length : 返回值的长度。它对字符串和列表都起作用
{{ value|length }}
{#如果 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。#}
3- filesizeformat :将值格式化为一个可读性高的文件尺寸
{{ value|filesizeformat }}
{# 如果 value 是 123456789,输出将会是 117.7 MB #}
4- date :格式化日期
value=datetime.datetime.now()
{{ value|date:"Y-m-d" }}
{# 不使用date:Nov. 9, 2018, 6:51 p.m. #}
{# date:2018-11-09 #}
5- slice:切片操作
{#前闭后开区间#}
<p>过滤器之slice:{{ ll|slice:'2:-1' }}</p>
{#支持步长#}
<p>过滤器之slice-字符串:{{ name|slice:'0:3:3' }}</p>
6- truncatechars :如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
{# 字符串 | truncatechars:显示的词数(三个起步)#}
<p>过滤器之truncatechars:{{ 'dafddfafgadfgaasdgadgfadaf'|truncatechars:5 }}</p>
{# da... #}
<p>过滤器之truncatewords:{{ '我 dfaf ga dfgaas 你 dgf adaf'|truncatewords:5 }}</p>
{# 我 dfaf ga dfgaas 你 ... #}
7- safe :是否转义输入框内的html、js元素等(使用-转义;不使用-不转义)
Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。
但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。
为了在Django中关闭HTML的自动转义,通过过滤器“|safe”的方式告诉Django这段代码是安全。
{# h1='<h1>你好</h1>' #}
<p>过滤器之不用safe:{{ h1 }}</p>
<p>过滤器之用safe:{{ h1|safe }}</p>
{# script='<script>alert(111)</script>' #}
<p>过滤器之不用safe:{{ script }}</p>
<p>过滤器之用safe:{{ script|safe }}</p>
8- 其他过滤器
过滤器描述示例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 }} 返回 Trueescape按HTML转义,比如将”<”转换为”<” filesizeformat增加数字的可读性,转换结果为13KB,89MB,3Bytes等{{ 1024 | filesizeformat }} 返回 1.0KBfirst返回列表的第1个元素,变量必须是一个列表 floatformat转换为指定精度的小数,默认保留1位小数{{ 3.1415926 | floatformat:3 }} 返回 3.142 四舍五入get_digit从个位数开始截取指定位置的数字{{ 123456 | get_digit:’1’}}join用指定分隔符连接列表{{ [‘abc’,’45’] | join:’’ }} 返回 abc45length返回列表中元素的个数或字符串长度 length_is检查列表,字符串长度是否符合指定的值{{ ‘hello’| length_is:’3’ }}linebreaks用<p>或<br>标签包裹变量{{ “Hi\n\nDavid”|linebreaks }} 返回<p>Hi</p><p>David</p>linebreaksbr用<br/>标签代替换行符 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-23stringformat字符串格式化,语法同python time返回日期的时间部分 timesince以“到现在为止过了多长时间”显示时间变量结果可能为 45days, 3 hourstimeuntil以“从现在开始到时间变量”还有多长时间显示时间变量 title每个单词首字母大写 truncatewords将字符串转换为省略表达方式{{ 'This is a pen' | truncatewords:2 }}返回``This is ...truncatewords_html同上,但保留其中的HTML标签{{ '<p>This is a pen</p>' | truncatewords:2 }}返回``<p>This is ...</p>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 %} …… {% endtag%}
标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})。
1- for标签:循环结构
列表的循环:
{% for person in person_list %}
<p>{{ person.name }}</p>
{% endfor %}
字典的循环:
{% for key in dic %}
<p>{{ key }}</p>
{% endfor %}
{% for val in dic.values %}
<p>{{ val }}</p>
{% endfor %}
{% for key,val in dic.items %}
<p>{{ key }}:{{ val }}</p>
{% endfor %}
模板:
{% for i in list %}
{{ i }}
{% endfor %}
1-1 查看循环信息:{{ forloop }}
{% for foo in ll %}
{{ forloop }}
<p>{{ forloop.first }}--->{{ forloop.counter0 }}--->{{ forloop.revcounter }}----->{{ foo }}</p>
{% endfor %}
{% for foo in ll %}
{% for i in person_list %}
取出外层是第几次循环
{{ forloop.parentloop.counter }}
<p>{{ forloop.first }}--->{{ forloop.counter0 }}--->{{ forloop.revcounter }}----->{{ foo }}</p>
{% endfor %}
{% endfor %}
{{ forloop }}的输出信息:
{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}
forloop.counter 当前循环的索引值(从1开始)forloop.counter0当前循环的索引值(从0开始)forloop.revcounter当前循环的倒序索引值(从1开始)forloop.revcounter0 当前循环的倒序索引值(从0开始)forloop.first 当前循环是不是第一次循环(布尔值)forloop.last当前循环是不是最后一次循环(布尔值)forloop.parentloop本层循环的外层循环
1-2 for …… empty :若循环对象为空执行empty内代码块
{% for person in person_list %}
<p>{{ person.name }}</p>
{% empty %}
<p>sorry,no person here</p>
{% endfor %}
2、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判断):
{% if …… %}
……
{% elif …… %}
……
{% else %}
……
{% endif %}
3、with 标签: 取别名,简化变量名
{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}
模板:
{% with 别名=原名 %}
{{ 别名 }}
……
{% endwith %}
4、csrf_token 标签:跨站请求伪造保护 {% csrf_token%}
五、自定义模板语法
1、自定义标签(参数不限,但不能放在if for语句中)- @register.simple_tag
确认app在setting内的INSTALLED_APPS注册app下创建一个templatetags(固定名称)的文件夹(模块)创建任意 .py 文件,如:my_tags.py # 第一步,导入template
from django import template #或者 from django.template import Library
from django.utils.safestring import mark_safe
register = template.Library() #register的名字是固定的,不可改变
@register.simple_tag(name = 'xxx') 装饰器内name可以对方法起别名
def simple_tag_multi(v1,v2):
return v1 * v2 #一定要有返回值
@register.simple_tag
def my_input(id,arg):
result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
return mark_safe(result) 在模板里:(新定定义的标签,过滤器,都要重启程序) {# 加载自己的标签文件名 #}
{% load mytag %}
{# 使用标签 #}
{% add_nb 'name'%}
{% add_3 'name1' 'name2'%} 多个参数以空格区分
1-1 @register.inclusion_tag --- 返回可迭代对象(qureyset对象)
注意:普通的自定义标签返回的都只是一个值,而inclusion_tag返回一个可迭代对象
# 第一步,导入template
from django import template #或者 from django.template import Library
register = template.Library() #register的名字是固定的,不可改变
# @register.inclusion_tag('模板路径',name=‘重命名’)
@register.inclusion_tag('test.html',name = 'xxx') 装饰器内name可以对方法起别名
def my_inclusion_1():
# 逻辑代码块……
ret = Book.object.all()
return {'books':ret} # 一定要有返回值,并且返回值必须是字典
@register.inclusion_tag('test.html')
def my_inclusion_2(v1,v2):
# 逻辑代码块……
ret = Book.object.all().filter(v1=v1,v2=v2)
return {'books':ret}
{# 模板中使用自定义inclusion_tag #}
{# 加载自己的标签文件名 #}
{% load mytag %}
{# 使用标签 #}
{% my_inclusion_1 %}
{% my_inclusion_2 'v1' 'v2'%} 多个参数以空格区分
2、自定义过滤器 - @register.filter
确认app在setting内的INSTALLED_APPS注册app下创建一个templatetags(固定名称)的文件夹(模块)创建任意 .py 文件,如:my_filter.py # 第一步,导入template
from django.template import Library
# 第二步,定义一个叫register的变量=template.Library()
register = Library()
# 第三步
# 装饰器内name可以对方法起别名
@register.filter(name='yyy')
def str_add(str1, str2):
# 业务逻辑……
return str1 + str2 # 一定要有返回值 在模板里:(新定定义的标签,过滤器,都要重启程序) 导入自己创建的过滤器文件
{% load myfilter %}
{{'name'|str_add:'hello'}}
有疑问加站长微信联系(非本文作者)