目录
自定义模板标签和过滤器
Django 的模板语言自带了丰富的标签和过滤器,能满足常见的表现逻辑需求。但是,这些内建的标签和过滤器可能缺少你需要的功能。
我们可以扩展模板引擎,使用 Python 自定义标签和过滤器,然后使用 {% load %} 标签加载,让自定义的标签和过滤器可在模板中使用。
自定义模板过滤器
自定义的过滤器其实就是普通的 Python 函数,接受一个或多个参数:
1. 变量的值(输入),不一定是字符串。
2. 参数的值,可以有默认值,也可以留空。
例如,对 {{ var|foo:"bar" }} 来说,传给 foo 过滤器的变量是 var ,参数是 "bar" 。因为模板语言没有提供异常处理功能,所以模板过滤器抛出的异常会以服务器错误体现出来。
过滤器的定义:
def cut(value, arg):
"""Removes all values of arg from the given string"""
return value.replace(arg, '')
这个过滤器的用法举例如下:
{{ somevariable|cut:"0" }}
多数过滤器没有参数。此时,在函数中留空参数即可。例如:
def lower(value): # 只有一个参数
"""Converts a string into all lowercase"""
return value.lower()
注册自定义的过滤器
定义好过滤器之后,要使用 Library 实例注册,让 Django 的模板语言知道它的存在:
register.filter('cut', cut)
register.filter('lower', lower)
Library.filter() 有两个参数:
1. 过滤器的名称,一个字符串。
2. 负责处理过滤器的函数,一个 Python 函数(不是函数名称的字符串形式)。
register.filter() 也可以作为装饰器使用:
@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')
@register.filter
def lower(value):
return value.lower()
自定义模板标签
标签能做任何事情,比过滤器复杂。Django 提供了一些快捷方式,简化了多数标签类型的编写。首先,我们将探讨这些快捷方式,然后说明在快捷方式不够用时如何从头开始编写标签。
例如有个 current_time 标签,它接受一个格式字符串,返回格式化后的时间字符串
据此, current_time 函数可以这么编写:
import datetime
from django import template
register = template.Library()
@register.simple_tag
def current_time(format_string):
return datetime.datetime.now().strftime(format_string)
如果模板标签需要访问当前上下文,注册标签时指定 takes_context 参数:
@register.simple_tag(takes_context=True)
def current_time(context, format_string):
timezone = context['timezone']
return your_get_current_time_method(timezone, format_string)
如果想为标签起个别的名称,指定 name 参数:
register.simple_tag(lambda x: x - 1, name='minusone')
@register.simple_tag(name='minustwo')
def some_function(value):
return value - 2
使用 simple_tag 装饰的函数可以接受任意个位置参数和关键字参数。例如:
@register.simple_tag
def my_tag(a, b, *args, **kwargs):
warning = kwargs['warning']
profile = kwargs['profile']
...
return ...
然后在模板中可以把任意个参数(以空格分开)传给这个标签。与 Python 代码一样,关键字参数的值使用等号( = )设定,而且必须放在位置参数后面。例如:
{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}
引入标签
首先,要定义一个接受参数的函数,生成一个字典,为结果提供数据。注意,我们只需返回一个字典,而不是其他复杂的数据结构。返回的字典在模板片段的上下文中使用。
def books_for_author(author):
books = Book.objects.filter(authors__id=author.id)
return {'books': books}
Author 对象名下的图书列表。我们将像这样使用这个标签:
{% books_for_author author %}
得到的结果如下:
<ul>
<li>The Cat In The Hat</li>
<li>Hop On Pop</li>
<li>Green Eggs And Ham</li>
</ul>
然后,创建用于渲染标签输出的模板。对这个标签来说,模板十分简单:
<ul>
{% for book in books %}
<li>{{ book.title }}</li>
{% endfor %}
</ul