我需要在django 1.6+中渲染模板之前组合连续的自定义模板标记。标签可以是与所选“兼容”标签列表相同或不同的标签。
我试图在调用nodelist
之前遍历模板render(context)
。这个循环将组合兼容的连续节点,但是我无法弄清楚如何在使用上下文渲染之前自动调用模板上的函数。
我看了
1)中间件 - 似乎没有人可以访问已编译的模板节点列表
2)自定义模板类 - 打破render
和render_to_response
等快捷方式
3)在视图中直接在模板上调用的函数 - 与上面相同的问题
有关如何实现这一目标的任何想法?
一些背景
基本思想是让不同的模板标签“一起渲染”,例如在一个简化的例子中:
{% tag_one "1A" "1B" %}{% tag_two "2A" %}
而不是渲染为两个独立的块:
[ 1A 1B ][ 2A ]
这将呈现为单个标记块:
[ 1A 1B 2A ]
标签的渲染功能背后有一些逻辑,但这里没有相关性......
答案 0 :(得分:1)
您可以使用此代码段:Capture template output as a variable并定义new filter,删除" ][
"或其中的任何内容。
示例(在templatetags
目录中的文件中):
from django import template
from django.template.defaultfilters import stringfilter
register = template.Library()
@register.tag(name='captureas')
def do_captureas(parser, token):
try:
tag_name, args = token.contents.split(None, 1)
except ValueError:
raise template.TemplateSyntaxError("'captureas' node requires a variable name.")
nodelist = parser.parse(('endcaptureas',))
parser.delete_first_token()
return CaptureasNode(nodelist, args)
class CaptureasNode(template.Node):
def __init__(self, nodelist, varname):
self.nodelist = nodelist
self.varname = varname
def render(self, context):
output = self.nodelist.render(context)
context[self.varname] = output
return ''
@register.filter(name='join_my_tags')
@stringfilter
def join_my_tags(text):
return text.replace(' ][ ', '')
用法(在您看来):
{% captureas my_tags %}{% tag_one "1A" "1B" %}{% tag_two "2A" %}{% endcaptureas %}
{{my_tags|join_my_tags}}
未经测试的替代方法:它不需要任何模板标签,但如果您想避免附带效果(例如搞乱您的javascript代码),则必须非常有选择性地替换。它与您的尝试类似,但在渲染之后起作用,而不是之前。
以这种方式修改你的观点:
from django.shortcuts import render
def index(request):
myresponse = render(request, 'index.html') # add your context object if you need it
return HttpResponse(myresponse.content.replace(' ][ ', '')) # you may eventually use regex or eventually even a full html parser (!) but please take performances in account :)
答案 1 :(得分:0)
你可以向前看"在提供给模板标记的解析器中。例如,以下内容使用parser.next_token()
来检查接下来的几个TemplateNodes
,看看它们是否兼容。
def my_tag(parser, token):
parse_me = [token]
# the following lines check if there are any additional nodes
# that we should combine and adds them to a list for processing
if parser.tokens:
while parser.tokens[0].token_type == 2 and parser.tokens[0].content[0:3] == 'my_':
parse_me.append(parser.next_token())
contents = ""
for tok in parse_me:
# apply some logic to combine the nodes
contents += tok.contents
return MyCustomNode(contents)