测试模板中是不是存在模板块
Posted
技术标签:
【中文标题】测试模板中是不是存在模板块【英文标题】:Test for existence of template block in a template测试模板中是否存在模板块 【发布时间】:2011-01-03 08:54:31 【问题描述】:我有一个结构,在我的基本模板中,(% block heading %
通常有一个页面标题:
base.html
<h2>% block heading %% endblock %</h2>
大多数时候,我会通过扩展 base 的模板传递这样的标题:
extends-base.html
% block heading %Super Cool Page!% endblock %
但是,对于一个特殊的页面,我不想有一个页面标题:
extends-base-special.html
% block heading %% endblock %
理想情况下,这应该排除<h2>
标签。现在,我可以让所有扩展模板都包含<h2>
标签,但这违反了 DRY,因为每个页面都应该具有相同的页面级标题元素。我更喜欢这样做(这似乎不起作用):
base-prefered.html
% if heading %
<h2>% block heading %% endblock %</h2>
% endif %
这在模板级别上是否可行,还是我必须为此投入视图?
【问题讨论】:
【参考方案1】:你可以把它包起来
% block noheader %
<h2>% block header %Super Cool Page!% endblock header %</h2>
% endblock noheader %
在没有标题的页面上
% block noheader %% endblock %
【讨论】:
是的,这就是我们最终的结果。尽管如此,通过后代模板测试块集的存在还是很有用的。 Ew。 +1,因为它解决了问题 - 但对于每个需要这个的模板来说,记住这一点很痛苦。 这是正确的解决方案,但% block noheader %
是一个坏名字,它使解决方案看起来比实际更hacker。更好的命名是% block header %
用于外部块,% block header-text %
用于内部块。然后名称更准确地反映了您希望能够在后代模板中覆盖的部分。
这是说在Django中这个问题没有合适的解决方案
这行得通,但是... bleh。 Rails 通过content_for?
很好地解决了这个问题【参考方案2】:
这样做:
base.html - 整个结构<h2>% block heading %% endblock %</h2>
base-without-heading.html - 使用 % block heading %% endblock %
扩展基础
然后扩展第一个或第二个模板。我相信这应该是最简单的方法。
顺便说一句。通过写作:
% if heading %
您实际上是在要求名称为“标题”的上下文中元素的布尔值。 django 标记语言的元素不在上下文中,所以你不能要求它们。你可以写一个标签,在上下文中添加一些东西,我曾经需要这样的东西并使用它,但我不相信这是要走的路。以上解决方案应该工作(我没有机器来检查这个),这是 IMNSHO 的最佳方式。
【讨论】:
【参考方案3】:Afaik 目前还没有真正好的和简单的解决方案。除了 czarchaic 提供的选项之外,您还可以编写自己的模板标签,如 Jarret Hardie's answer 到 "How to test for use of a django template block?" 中所述。但是,恕我直言,最好和最优雅的方式是 % capture as ... %
模板标签 - 不幸的是它还没有实现:https://code.djangoproject.com/ticket/6378
【讨论】:
是的。这一直是我对 Django 的唯一主要批评。【参考方案4】:我知道我迟到了,但对于任何(像我一样)仍在寻找解决该问题的人,这里是我的:
我创建了一个自定义 TemplateBackend,它将给定模板中每个块的名称放在一个名为“FILLED_BLOCKS”的上下文变量中。
这是代码:(注意:如果您多次扩展模板,它可能无法正常工作,但我想您可以通过添加一点递归或其他东西轻松解决这个问题。这不是我需要的)
from django.template.backends.django import DjangoTemplates, Template, reraise, TemplateDoesNotExist
from django.template.context import make_context
from django.template.engine import Engine
from django.template.loader_tags import ExtendsNode
class CustomBackend(DjangoTemplates):
def from_string(self, template_code):
return CustomTemplate(self.engine.from_string(template_code))
def get_template(self, template_name):
try:
return CustomTemplate(self.engine.get_template(template_name), self)
except TemplateDoesNotExist as exc:
reraise(exc, self)
class CustomTemplate(Template):
def get_filled_blocks(self):
nodes = self.template.nodelist.get_nodes_by_type(ExtendsNode)
if len(nodes) == 0:
return []
blocks = []
for node in nodes:
for block in node.blocks.values():
if len(block.nodelist) != 0:
blocks.append(block.name)
return blocks
def render(self, context=None, request=None):
context['FILLED_BLOCKS'] = self.get_filled_blocks()
context = make_context(context, request, autoescape=self.backend.engine.autoescape)
try:
return self.template.render(context)
except TemplateDoesNotExist as exc:
reraise(exc, self.backend)
只需将此文件的路径放入您的 settings.py 中的 TEMPLATES['BACKEND']
像这样在你的模板中使用它:
% if 'heading' in FILLED_BLOCKS %
<h2>% block heading %% endblock %</h2>
% endif %
【讨论】:
以上是关于测试模板中是不是存在模板块的主要内容,如果未能解决你的问题,请参考以下文章