模板-过滤器&标签

模板值过滤器


对一个 Python开发者来说,写一个自己的模板语言就象是某种“成人礼”一样! 如果你还没有完成一个自己的 模板语言,好好考虑写一个,这是一个非常有趣的锻炼。
 
 
模板过滤器是在变量被显示前修改它的值的一个简单方法。 过滤器使用管道字符,如下所示:
 
{{ name|lower }}
过滤管道可以被* 套接* ,既是说,一个过滤器管道的输出又可以作为下一个管道的输入,如此下去。 下面的例子实现查找列表的第一个元素并将其转化为大写。
{{ my_list|first|upper }}
有些过滤器有参数。 过滤器的参数跟随冒号之后并且总是以双引号包含。
{{ bio|truncatewords:"30" }}
语法: {{obj|filter__name:param}}
Default 如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如: {{ value|default:"nothing" }}
Length
返回值的长度。它对字符串和列表都起作用。例如:
{{ value|length }}
如果 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。
Filesizeformat
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '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" }}
Truncatechars
如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:要截断的字符数
例如:
{{ value|truncatechars:9 }}
Safe
Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。比如:
value="<a href="">点击</a>"
{{ value|safe}}
addslashes : 添加反斜杠到任何反斜杠、单引号或者双引号前面。 这在处理包含JavaScript的文本时是非常有用的。
 
这里简单介绍一些常用的模板的过滤器,更多详见

 

模板语法之标签


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

for标签

遍历每一个元素:
{% for person in person_list %}
   <p>{{ person.name }}</p>
{% endfor %}
给标签增加一个 reversed 使得该列表被反向迭代:
{% for athlete in athlete_list reversed %}
...
{% endfor %}
遍历一个字典:
{% for key,val in dic.items %}
   <p>{{ key }}:{{ val }}</p>
{% endfor %}
 
可以嵌套使用 {% for %} 标签
 
 

for ... empty

在执行循环之前先检测列表的大小是一个通常的做法, 因为这种做法十分常见,所以`` for`` 标签支持一个可选的`` {% empty %}`` 分句,通过它我们可以定义当列表为空时的输出内容

for?标签带有一个可选的{%?empty?%}?从句,以便在给出的组是空的或者没有被找到时,可以有所操作。
{% for person in person_list %}
   <p>{{ person.name }}</p>
{% empty %}
   <p>sorry,no person here</p>
{% endfor %}
 

`` forloop`` 模板变量

forloop.counter 总是一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,所以在第一次循环时 forloop.counter 将会被设置为1。
{% for item in todo_list %}
    <p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}

 

forloop.counter0 类似于 forloop.counter ,但是它是从0计数的。 第一次执行循环时这个变量会被设置为0。
 
forloop.revcounter 是表示循环中剩余项的整型变量。 在循环初次执行时 forloop.revcounter 将被设置为序列中项的总数。 最后一次循环执行中,这个变量将被置1。
 
forloop.revcounter0 类似于 forloop.revcounter ,但它以0做为结束索引。 在第一次执行循环时,该变量会被置为序列的项的个数减1。
 
forloop.first 是一个布尔值,如果该迭代是第一次执行,那么它被置为```` 在下面的情形中这个变量是很有用的:
{% for object in objects %}
    {% if forloop.first %}<li class="first">{% else %}<li>{% endif %}
    {{ object }}
    </li>
{% endfor %}

 

forloop.last 是一个布尔值;在最后一次执行循环时被置为True。 一个常见的用法是在一系列的链接之间放置管道符(|)
{% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}
上面的模板可能会产生如下的结果:
Link1 | Link2 | Link3 | Link4
另一个常见的用途是为列表的每个单词的加上逗号。
Favorite places:
{% for p in places %}{{ p }}{% if not forloop.last %}, {% endif %}{% endfor %}
forloop.parentloop 是一个指向当前循环的上一级循环的 forloop 对象的引用(在嵌套循环的情况下)。 例子在此:
{% for country in countries %}
    <table>
    {% for city in country.city_list %}
        <tr>
        <td>Country #{{ forloop.parentloop.counter }}</td>
        <td>City #{{ forloop.counter }}</td>
        <td>{{ city }}</td>
        </tr>
    {% endfor %}
    </table>
{% endfor %}
forloop 变量仅仅能够在循环中使用。 在模板解析器碰到{% endfor %}标签后,forloop就不可访问了。

ifequal/ifnotequal

{% ifequal %} 标签比较两个值,当他们相等时,显示在 {% ifequal %} 和 {% endifequal %} 之中所有的值。
下面的例子比较两个模板变量 user 和 currentuser :
{% ifequal user currentuser %}
    <h1>Welcome!</h1>
{% endifequal %}

 

参数可以是硬编码的字符串,随便用单引号或者双引号引起来
{% ifequal section 'sitenews' %}
    <h1>Site News</h1>
{% endifequal %}

{% ifequal section "community" %}
    <h1>Community</h1>
{% endifequal %}

和 {% if %} 类似, {% ifequal %} 支持可选的 {% else%} 标签

{% ifequal section 'sitenews' %}
    <h1>Site News</h1>
{% else %}
    <h1>No News Here</h1>
{% endifequal %}

 

只有模板变量,字符串,整数和小数可以作为 {% ifequal %} 标签的参数

if/else

{% if %} 标签检查(evaluate)一个变量,如果这个变量为真(即,变量存在,非空,不是布尔值假),系统会显示在 {% if %} 和 {% endif %} 之间的任何内容,例如

{% if today_is_weekend %}
    <p>Welcome to the weekend!</p>
{% endif %}
{% else %} 标签是可选的:
{% if today_is_weekend %}
    <p>Welcome to the weekend!</p>
{% else %}
    <p>Get back to work.</p>
{% endif %}
 
{% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。
{% if num > 100 or num < 0 %}
   <p>无效</p>
{% elif num > 80 and num < 100 %}
   <p>优秀</p>
{% else %}
   <p>凑活吧</p>
{% endif %}

 

 
Python 的“真值”
在Python和Django模板系统中,以下这些对象相当于布尔值的False
空列表([] )  ,空元组(() ) , 空字典({} ) ,空字符串('' ), 零值(0 ), 特殊对象None, 对象False(很明显)
提示:你也可以在自定义的对象里定义他们的布尔值属性(这个是python的高级用法)。
除以上几点以外的所有东西都视为`` True``
 

{% if %} 标签接受 and , or 或者 not 关键字来对多个变量做判断 ,或者对变量取反( not )

{% if %} 标签不允许在同一个标签中同时使用 and 和 or ,因为逻辑上可能模糊的,例如,如下示例是错误的: 比如这样的代码是不合法的:
{% if athlete_list and coach_list or cheerleader_list %}
系统不支持用圆括号来组合比较操作。 如果你确实需要用到圆括号来组合表达你的逻辑式,考虑将它移到模板之外处理,然后以模板变量的形式传入结果吧。 或者,仅仅用嵌套的{% if %}标签替换吧,就像这样:
{% if athlete_list %}
    {% if coach_list or cheerleader_list %}
        We have athletes, and either coaches or cheerleaders!
    {% endif %}
{% endif %}

 

多次使用同一个逻辑操作符是没有问题的,但是我们不能把不同的操作符组合起来
 
并没有 {% elif %} 标签, 请使用嵌套的`` {% if %}`` 标签来达成同样的效果:
 
一定要用 {% endif %} 关闭每一个 {% if %} 标签。
 

With

使用一个简单地名字缓存一个复杂的变量,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的
例如:
{% with total=business.employees.count %}
   {{ total }} employee{{ total|pluralize }}
{% endwith %

csrf_token

 
这个标签用于跨站请求伪造保护
不想让别人随意给这个服务器发送post请求
可以在form标签内部加上  {{csrf_token}}
rander将{{csrf_token}}标签渲染为一个type=hidden的input标签,在点击post提交请求时,会多提交一个键值对,Django的中间件会根据这个键值对来确定访问的安全性

自定义标签与过滤器

1、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.
2、在app中创建templatetags模块(模块名只能是templatetags)
3、创建任意 .py 文件,如:my_tags.py
from django import template
from django.utils.safestring import mark_safe
 
register = template.Library()?? #register的名字是固定的,不可改变
@register.filter
def filter_multi(v1,v2):
    return? v1 * v2
@register.simple_tag
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)
 
 
from django import template
from django.utils.safestring import mark_safe
register = template.Library()?? #register的名字是固定的,不可改变
@register.filter
def filter_multi(v1,v2):
   return? v1 * v2
 
 
@register.simple_tag
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、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py
{% load my_tags %}
5、使用simple_tag和filter(如何调用)
-------------------------------.html
{% load xxx %}??
??????
# num=12
{{ num|filter_multi:2 }} #24
{{ num|filter_multi:"[22,333,4444]" }}
{% simple_tag_multi 2 5 %}? 参数不限,但不能放在if for语句中
{% simple_tag_multi num 5 %}
注意:filter可以用在if等语句后,simple_tag不可以
{% if num|filter_multi:30 > 100 %}
    {{ num|filter_multi:30 }}
{% endif %}
 
 

注释

注释使用 {# #}, 用这种语法的注释不能跨越多行。 这个限制是为了提高模板解析的性能 :
{# This is a comment #}
 
如果要实现多行注释,可以使用`` {% comment %}`` 模板标签,就像这样:
{% comment %}
This is a
multi-line comment.
{% endcomment %}
 

 

 
 
posted @ 2020-02-21 17:39  感动#心  阅读(260)  评论(0编辑  收藏  举报