包含标签¶
django.template.Library.inclusion_tag()¶
另一种常见的模板标签会为 另一个 模板渲染数据。例如, Django 的后台利用自定义模板标签在表单页的底部展示按钮。这些按钮看起来一样,但是连接目标根据被编辑的对象不同而不同——所以,这是一个极好的例子,展示如何用当前对象的细节填充小模板。(在后台例子中,即 submit_row 标签。)
这种标签被称为“包含标签”。
编写包含标签可能最好通过实例来展示。让我们编写一个标签,它会将指定 Poll 对象(就像 教程 中创建的那样)的选项以列表输出。我们像这样使用标签:
{% show_results poll %}
输出看起来像这样:
- First choice
- Second choice
- Third choice
首先,定义一个函数,接受参数,并返回一个字典。此处的要点是我们只需返回一个字典,不是任何其它复杂的东西。这将作为一个模板上下文被模板碎片使用。例子:
def show_results(poll):
choices = poll.choice_set.all()
return {'choices': choices}
随后,创建用于渲染标签输出的模板。该模板是标签的一个固有特性:标签作者指定它,而不是模板设计者。跟随我们的例子,模板非常简单:
{% for choice in choices %}
{{ choice }}{% endfor %}
现在,在 Library 对象上调用 inclusion_tag() 创建并注册该包含标签。如果上述模板位于一个名为 results.html 的文件中,在模板加载器搜索的目录中,我们像这样注册该标签:
# Here, register is a django.template.Library instance, as before
@register.inclusion_tag('results.html')
def show_results(poll):
...
from django.template.loader import get_template
t = get_template('results.html')
register.inclusion_tag(t)(show_results)
在第一次创建该函数时。
有时候,你的包含标签可能要求超多参数,模板作者不得不传入所有参数,并牢记它们的顺序,非常痛苦。为了解决此问题, Django 为包含标签提供了一个 take_context 选项。如果在创建模板标签时指定了 takes_context,该标签将没有必要的参数,底层 Python 函数将只有一个参数——标签创建时的模板上下文。
举个例子,假设你编写了一个包含标签,总会在一个包含指向首页的 home_link 和 home_title 的上下文环境下使用。Python 函数看起来会像这样:
@register.inclusion_tag('link.html', takes_context=True)
def jump_link(context):
return {
'link': context['home_link'],
'title': context['home_title'],
}
注意,该函数的第一个参数 必须 是 context。
在 register.inclusion_tag() 行,我们制定了模板名并设置 takes_context=True。以下是模板 link.html 的样子:
Jump directly to {{ title }}.
后面,当你想用该自定义标签时,加载它的库,并不带任何参数的调用它,像这样:
{% jump_link %}
注意,只要使用了 takes_context=True,就无需为模板标签传递参数。它自动从上下文获取。
takes_context 参数默认为 False。当其为 True,标签会被传入上下文对象,像本例展示的那样。这是本例和之前的 包含标签 实例的唯一不同之处。
包含标签 函数能接受任意个数的位置或关键字参数。例子:
@register.inclusion_tag('my_template.html')
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 %}