Django - 模板层 - 变量、过滤器、标签 - DTL语言

2019-04-13 17:31发布

目录 一、模板概念 二、 模板语法 - 变量 : {{ 变量 }} 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 = "It is now %s." % 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了该变量#}

模板语言之变量

字符串:{{ name }}

数字:{{ age }}

列表:{{ ll }}

元组:{{ tu }}

字典:{{ dic }}

{#只写函数名:相当于函数名(),执行该函数,显示的是返回值#}

函数:{{ test }}

{#对象调用显示内存地址#}

对象:{{ lqz }}

{# person_list=[p1,p2] #}

列表套对象:{{ person_list }}

{# person_dic={'p1':p1} #}

字典套对象:{{ person_dic }}

2、深度取值 - 获取对象内部值

深度查询

{# 一层 #}

列表第0个值:{{ ll.0 }}

列表第4个值:{{ ll.3 }}

字典取值:{{ dic.name }}

字典取列表值:{{ dic.ll }}

{# 二层 #}

对象取数据属性:{{ p1.name }}

对象取绑定给对象的函数属性:{{ p1.get_name }}

对象取绑定给类的函数属性:{{ p1.cls_test }}

对象取静态方法:{{ p1.static_test }}

把对象列表中,其中对象的一个年龄属性取出来:{{ person_list.1.age }}

{# 注意:不能调有参数的方法 #}

字符串的方法:{{ name.upper }}

三、模板语法 - 过滤器 :{{ 位置参数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:切片操作

{#前闭后开区间#}

过滤器之slice:{{ ll|slice:'2:-1' }}

{#支持步长#}

过滤器之slice-字符串:{{ name|slice:'0:3:3' }}

6- truncatechars :如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。

{# 字符串 | truncatechars:显示的词数(三个起步)#}

过滤器之truncatechars:{{ 'dafddfafgadfgaasdgadgfadaf'|truncatechars:5 }}

{# da... #}

过滤器之truncatewords:{{ '我 dfaf ga dfgaas 你 dgf adaf'|truncatewords:5 }}

{# 我 dfaf ga dfgaas 你 ... #}

7- safe :是否转义输入框内的html、js元素等(使用-转义;不使用-不转义)

Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。 但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。 为了在Django中关闭HTML的自动转义,通过过滤器“|safe”的方式告诉Django这段代码是安全。 {# h1='

你好

' #}

过滤器之不用safe:{{ h1 }}

过滤器之用safe:{{ h1|safe }}

{# script='' #}

过滤器之不用safe:{{ script }}

过滤器之用safe:{{ script|safe }}

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 }} 返回 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 %} …… {% endtag%}

标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})。

1- for标签:循环结构

列表的循环: {% for person in person_list %}

{{ person.name }}

{% endfor %} 字典的循环: {% for key in dic %}

{{ key }}

{% endfor %} {% for val in dic.values %}

{{ val }}

{% endfor %} {% for key,val in dic.items %}

{{ key }}:{{ val }}

{% endfor %} 模板: {% for i in list %} {{ i }} {% endfor %}

1-1 查看循环信息:{{ forloop }}

{% for foo in ll %} {{ forloop }}

{{ forloop.first }}--->{{ forloop.counter0 }}--->{{ forloop.revcounter }}----->{{ foo }}

{% endfor %} {% for foo in ll %} {% for i in person_list %} 取出外层是第几次循环 {{ forloop.parentloop.counter }}

{{ forloop.first }}--->{{ forloop.counter0 }}--->{{ forloop.revcounter }}----->{{ foo }}

{% 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 %}

{{ person.name }}

{% empty %}

sorry,no person here

{% endfor %}

2、if标签:逻辑判断

{% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。 {% if num > 100 or num < 0 %}

无效

{% elif num > 80 and num < 100 %}

优秀

{% else %}

凑活吧

{% 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

  1. 确认app在setting内的INSTALLED_APPS注册
  2. app下创建一个templatetags(固定名称)的文件夹(模块)
  3. 创建任意 .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 = "" %(id,arg,) return mark_safe(result)  
  4. 在模板里:(新定定义的标签,过滤器,都要重启程序) {# 加载自己的标签文件名 #} {% 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

  1. 确认app在setting内的INSTALLED_APPS注册
  2. app下创建一个templatetags(固定名称)的文件夹(模块)
  3. 创建任意 .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 # 一定要有返回值  
  4. 在模板里:(新定定义的标签,过滤器,都要重启程序) 导入自己创建的过滤器文件 {% load myfilter %} {{'name'|str_add:'hello'}}