我已经创建了一个包含标记,但是我希望能够使模板可选择配置。似乎没有开箱即用的支持,所以我想看看人们如何做到这一点 - 也许是一个方法首先搜索模板目录中的特定模板名称,然后再回到默认模板。 / p>
@register.inclusion_tag('foo.html', takes_context=True)
答案 0 :(得分:31)
我需要这样做时使用simple_tag:
from django.template import Library, loader, Context
@register.simple_tag(takes_context=True)
def my_tag(context, template_name):
var1 = ...
t = loader.get_template(template_name)
return t.render(Context({
'var1': var1,
...
}))
答案 1 :(得分:9)
答案 2 :(得分:6)
inclusion_tag
装饰器只是一个快捷方式 - 它是一种使用特定上下文渲染特定模板的简单方法。一旦你想要移出它,它就再也无法帮助你了。但这只是意味着您必须在很长的路上编写标记,如文档中所述,并将您想要的模板作为参数传递。
答案 3 :(得分:4)
我不得不为一个项目做这样的事情,因为我们需要不止一个这种包含标签,我做了一个基于django inclusion_tag装饰器的装饰器。这是代码:
# -*- 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
您必须返回带有模板(或模板列表)和上下文字典的元组。请注意,您必须在装饰器调用中传递寄存器(库实例):
from somewhere import inclusion_tag
@inclusion_tag(register)
def display_formset(formset):
template_name = FORMSET_TEMPLATES.get(formset.model,
'includes/inline_formset.html')
return (template_name, {'formset': formset})
希望这有帮助
答案 4 :(得分:0)
解决方案可以是常规inclusion_tag
,可将动态模板名称传递给context
。
像这样:
# templatetags/tags.py
@register.inclusion_tag('include_tag.html', takes_context=True)
def tag_manager(context):
context.update({
'dynamic_template': resolve_template(context),
})
return context
模板:
<!-- include_tag.html -->
{% include dynamic_template %}
这里的技巧是,当我致电{% tag_manager %}
时,它包含include_tag.html
,而resolve_template()
又包含var obj = {
parentKey : {
nestedKey1 : "value",
nestedKey2 : function () {
var c = obj.parentKey;
//console.log("we get "+ c.nestedKey1 +" & "+ c.nestedKey3);
//you can update values
//obj.parentKey.nestedKey1 = "new value";
console.log("we get "+ c.nestedKey1 +" & "+ c.nestedKey3);
return "we get "+ c.nestedKey1 +" & "+ c.nestedKey3;
},
nestedKey3 : "another value"
}
};
obj.parentKey.nestedKey2();
var an = window["obj"]["parentKey"]["nestedKey3"];
console.log(an);
返回的模板(为简洁起见,不包括在内)。
希望这会有所帮助......