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

wx57f63dceec388 · · 356 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

参考链接: Django-模板系统

目录 

一、模板概念 

二、 模板语法 - 变量 : {{ 变量 }} 

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转义,比如将”<”转换为”&lt” 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'}}



有疑问加站长微信联系(非本文作者)

本文来自:51CTO博客

感谢作者:wx57f63dceec388

查看原文:Django - 模板层 - 变量、过滤器、标签 - DTL语言

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

356 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传