Django templatetag范围强迫我做额外的查询

时间:2010-01-16 10:50:07

标签: django scope templatetags

问题在于,如果我将模板标签调用到块中 它填补了我通常的上下文[varname] =的东西, 然后,如果我需要将该变量放入另一个块,我必须调用 再次模板标签。这对我来说意味着额外的数据库查询,这是真的 我想避免的事情。

此模板标签在扩展的基本模板中调用 许多其他模板,所以我不能只改变所有要传递的视图 在某种情况下,它没有意义(WET原理?)

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

我正在考虑编写一个可以使用的模板标签 内部上下文结构将变量放在全局上下文中, 但是我觉得这样做太内疚了。

你会如何解决这个问题?

4 个答案:

答案 0 :(得分:3)

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

问题是:是否在命名块中调用此标记?如果是,那么你有几个潜在的问题。

  1. {% block %}在Context堆栈上推送一个新的dict,当它到达匹配的`{%endblock%}'时将其弹出。这意味着在块中创建的任何上下文值在块退出时基本上都超出了范围。

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

  3. 如果<{1>}内没有标记,那么上下文值应该可用于其后面的所有代码,可以是基本模板,任何包含的模板和(我认为)任何扩展模板。

    这是其中一种情况,即建立一套仔细的测试可能会节省您的时间和眼泪。

    或者,如果您始终访问此值,则可以将其放在context processor中,以确保其可用性。

    评论更新:好的,有时间带来大枪! Django模板中最令人恼火的,长期存在的错误之一是作为顶级上下文值的callable(即函数)(与 上下文值的dict-values / methods 的函数相对) )未被调用!此票证已超过2年,需要修复大约10行代码。我们有几个重量级的DB调用,如果模板缓存已过期,我们只想发生 。所以我们a)MonkeyPatched模板{% block %}代码来修复可调用问题,然后b)咖喱函数以获得所有必要参数如果需要,因为你不能将params传递给模板“语言”中的函数。

答案 1 :(得分:2)

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

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

刚刚从Liviu, Agile Bear发现了这个伎俩(所有功劳归于他)

而不是做

context['some_var']='some value'

DO

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

可能不是一本书编码练习,但效果不错