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



一、模板概念

你可能已经注意到我们在例子视图中返回文本的方式有点特别。 也就是说,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 }} 返回 True
escape 按HTML转义,比如将”<”转换为”&lt”  
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 用<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-23
stringformat 字符串格式化,语法同python  
time 返回日期的时间部分  
timesince 以“到现在为止过了多长时间”显示时间变量 结果可能为 45days, 3 hours
timeuntil 以“从现在开始到时间变量”还有多长时间显示时间变量  
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

  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 = "<input type='text' id='%s' class='%s' />" %(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'}}

猜你喜欢

转载自blog.csdn.net/qq_33961117/article/details/83900608