5

问题是,如果我将一个模板标签调用到一个块中并且它用通常的上下文 [varname]=something 填充我一个变量,那么如果我需要将该变量放入另一个块中,我必须再次调用模板标签。这对我来说意味着额外的数据库查询,这确实是我试图避免的事情。

此模板标签在由许多其他模板扩展的基本模板中调用,因此我不能只更改所有视图以将某些内容传递给上下文,这没有任何意义(WET 原则?)

即使是上下文处理器也不好,因为我不想为站点中呈现的每个页面调用它,即使是那些不基于该模板的页面。

我正在考虑编写一个模板标签,它会使用内部上下文结构将变量放在全局上下文中,但这样做我会感到内疚。

你将如何解决这个问题?

4

4 回答 4

3

你说,“这个模板标签在一个由许多其他模板扩展的基本模板中被调用。”

问题是:这个标签是从命名块中调用的吗?如果是这样,那么你有几个潜在的问题。

  1. {% block %}在上下文堆栈上推送一个新字典,并在到达匹配的“{% endblock %}”时将其弹出。这意味着在块中创建的任何上下文值在块退出时基本上已经超出了范围。

  2. 如果此块被扩展基本模板的其他模板覆盖,则该值可能根本不可用,除非您执行 a {{block.super}},即使那样我也不确定该值是否可用于进行扩展的模板。

如果标签不是从 a 中调用的,{% block %}那么上下文值应该可用于它后面的所有代码,无论是在基本模板、任何包含的模板和(我认为)任何扩展模板中。

这是构建一组仔细测试可能会节省您的时间和眼泪的情况之一。

或者,如果您总是访问此值,则可以将其放入上下文处理器中,以保证其可用性。

更新评论:好的,是时候引入大炮了!Django 模板中最烦人、长期存在的错误之一是,作为顶级上下文值的可调用对象(即函数)(与作为上下文值的字典值/方法函数相反)没有被调用!这张票已经超过 2 年了,大约需要 10 行代码来修复。我们有几个重量级的数据库调用,我们只希望在模板缓存过期时发生。所以我们 a) MonkeyPatched 模板_resolve_lookup()代码以修复可调用问题,然后 b) curry 函数以在需要时具有所有必要的参数因为您不能将参数传递给模板“语言”中的函数。

于 2010-01-16T19:10:01.707 回答
2

我认为您已经准确地描述了这种情况下的局限性。最可维护的解决方案可能会涉及到模板继承链的一些重组,尽管在不了解细节的情况下很难说。您能否在继承层次结构中引入一个新模板,可能在金字塔顶部附近的某个地方,但它仅由需要此数据的模板继承,并且单个块包含您需要此数据的整个区域?然后可以将该大块细分为继承模板将覆盖的较小块。如果您在该块的开头调用您的模板标签,则其中的所有块(包括继承模板)都可以访问数据。

更新:没有看到你的模板我不能说太多,但是在继承链中间引入一个新模板很少涉及“更改所有模板”,在一个理智的继承结构中,它通常可以通过只更改一个来完成或其他两个模板。而且我认为我的建议实际上不是黑客,它只是更好的设计。如果您在站点的某些部分而不是其他部分需要某条数据,则应该有一个特定的单一模板,您可以指向并说“这个模板代表了引入这条数据的逻辑层,并包含需要该数据的站点部分。”

于 2010-01-16T20:55:02.950 回答
0

您只是想减少数据库查询的数量还是正在寻找一个聪明的解决方案?

如果是前者,我肯定会使用缓存。在您的情况下,片段缓存会起作用吗?如果没有,也许您可​​以将缓存放在模板标记代码中(假设它不是您使用的 Django 自己的模板标记之一)?

于 2010-01-16T18:11:17.750 回答
0

刚刚从敏捷熊 Liviu那里发现了这个技巧(所有功劳归功于他)

而不是做

context['some_var']='some value'

context.dicts[0]['some_var']='some value'

可能不是按书本编码的做法,但效果很好

于 2013-08-05T15:44:57.343 回答