# -*- coding: utf-8 -*-
from django import template
from inspect import getargspec
from django.template.context import Context
from django.template import Node, generic_tag_compiler, Variable
from django.utils.functional import curry
def inclusion_tag(register, context_class=Context, takes_context=False):
def dec(func):
params, xx, xxx, defaults = getargspec(func)
if takes_context:
if params[0] == 'context':
params = params[1:]
else:
raise TemplateSyntaxError("Any tag function decorated with takes_context=True must have a first argument of 'context'")
class InclusionNode(Node):
def __init__(self, vars_to_resolve):
self.vars_to_resolve = map(Variable, vars_to_resolve)
def render(self, context):
resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
if takes_context:
args = [context] + resolved_vars
else:
args = resolved_vars
file_name, extra_context = func(*args)
from django.template.loader import get_template, select_template
if not isinstance(file_name, basestring) and is_iterable(file_name):
t = select_template(file_name)
else:
t = get_template(file_name)
self.nodelist = t.nodelist
new_context = context_class(extra_context, autoescape=context.autoescape)
# Copy across the CSRF token, if present, because inclusion
# tags are often used for forms, and we need instructions
# for using CSRF protection to be as simple as possible.
csrf_token = context.get('csrf_token', None)
if csrf_token is not None:
new_context['csrf_token'] = csrf_token
return self.nodelist.render(new_context)
compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, InclusionNode)
compile_func.__doc__ = func.__doc__
register.tag(getattr(func, "_decorated_function", func).__name__, compile_func)
return func
return dec
6条答案
按热度按时间6l7fqoea1#
当我需要这样做时,我使用simple_tag:
p3rjfoxz2#
这个帖子救了我的命:http://djangosnippets.org/snippets/1329/
关键是要添加一个“虚拟模板”:
qf9go6mv3#
inclusion_tag
装饰器只是一个快捷方式--它是一种用特定的上下文呈现特定模板的简单方法。一旦你想离开它,它就不再能帮你了。但这只意味着你必须像文档中解释的那样写一个很长的标记,并将你想要的模板作为参数传递。iyfjxgzm4#
我曾经在一个项目中做过类似的事情,因为我们需要不止一个这样的inclusion标签,所以我基于django inclusion_tag decorator做了一个decorator。
你必须返回一个带有模板(或模板列表)和上下文指令的元组。注意你必须在装饰器调用中传递register(Library示例):
希望这能帮上忙
4ioopgfo5#
一个解决方案可以是常规
inclusion_tag
,它将动态模板名称传递给context
。就像这样:
和模板:
这里的技巧是,当我调用
{% tag_manager %}
时,它包含include_tag.html
,而include_tag.html
又包含由resolve_template()
返回的模板(为简洁起见,没有包含)。希望这能帮上忙...
tjvv9vkg6#
@cvng的answer的变体,不需要创建
include_tag.html
模板: