首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >查询它需要的变量的模板?

查询它需要的变量的模板?
EN

Stack Overflow用户
提问于 2009-12-03 22:11:33
回答 1查看 1.4K关注 0票数 12

我希望能够从文件中实例化模板(大概使用django.template.loader.get_template(文件名) ),然后确定应该在传递的任何上下文中定义的变量集。

我以为模板对象上会有一个方法,但似乎没有。

我读了那些文档,我发现最接近的是:

http://docs.djangoproject.com/en/1.0/topics/templates/#using-the-built-in-reference

这意味着进入管理界面查看与给定视图关联的所有变量。

我不想通过管理界面,因为我想通过编程-我正在尝试编写测试。

我使用Django版本(1,0,2,'final',0)

更新:

我尝试了synack的答案,发现(用filter_expression.token替换为filter_expression.var,获得没有标记的变量的实际名称等等)它返回在模板中本地定义的变量,但对于在它扩展的父变量中定义的变量无效。

例如,假设我在两个文件中有模板:

toyparent.html:

代码语言:javascript
复制
{%block base_results%}
Django is {{adjective}}
{%endblock base_results%}

toychild.html:

代码语言:javascript
复制
{% extends "toyparent.html" %}

{%block base_results%}
    {{block.super}}
    I {{verb}} it.
{%endblock base_results %}

然后加载子模板:

代码语言:javascript
复制
>>> toy=django.template.loader.get_template('toychild.html')

这样可以适当地显示:

代码语言:javascript
复制
>>> toy.render(django.template.Context(dict(adjective='cool',verb='heart')))
u'\n    \nDjango is cool\n\n    I heart it.\n\n'

但我找不到这两个变量:

代码语言:javascript
复制
>>> v=toy.nodelist.get_nodes_by_type(VariableNode)
>>> for k in v: print k.filter_expression.var
...
block.super
verb
EN

回答 1

Stack Overflow用户

发布于 2009-12-03 22:59:37

您可以直观地检查一个模板,并在该模板的节点列表中观察到任何“可变节点”对象的存在:

代码语言:javascript
复制
>>> from django.template import Template, Context
>>> t = Template("Django is {{ adjective }} and I {{ verb }} it.")
>>> t.nodelist
[<Text Node: 'Django is '>, <Variable Node: adjective>, <Text Node: ' and I '>, <Variable Node: verb>, <Text Node: ' it.'>]

这些是VariableNode类型的类,它是一个可以直接导入以用于比较的类。任何Node实例都有一个可以针对节点列表调用的get_nodes_by_type()方法,该方法返回模板的该类型的所有节点。示例:

代码语言:javascript
复制
>>> from django.template import VariableNode
>>> varnodes = t.nodelist.get_nodes_by_type(VariableNode)
>>> varnodes
[<Variable Node: adjective>, <Variable Node: verb>]

现在,您有了模板的变量列表。这需要更进一步,以提取每个变量的实际名称,而不会在其repr名称上出现愚蠢的字符串切片技巧。

变量名称本身存储在filter_expression.token中,用于每个VariableNode

代码语言:javascript
复制
>>> varnodes[0].filter_expression.token
u'adjective'

因此,一个简单的列表理解就可以获得模板的所有变量名称:

代码语言:javascript
复制
>>> template_vars = [x.filter_expression.token for x in varnodes]
>>> template_vars
[u'adjective', u'verb']

所以,不是最简单的解决方案,但如果有更好的方法,我不知道它。

奖金:A功能!!

代码语言:javascript
复制
from django.template import VariableNode
def get_template_vars(t):
   varnodes = t.nodelist.get_nodes_by_type(VariableNode)
   return [x.filter_expression.token for x in varnodes]

好吧,它毕竟不是那么复杂!

后续编辑:从父模板获取变量

(这个后续行动是使用来自更新问题的信息)。

这就是它实际上变得复杂的地方,因为玩具模板的节点列表是单个ExtendsNode (在本例中)。

代码语言:javascript
复制
>>> toy.nodelist
[<ExtendsNode: extends "mysite/toyparent.html">]

我可以想象,在较大的模板中,可能有多个ExtendsNode对象。无论如何,如果检查ExtendsNode并从中提取父模板,则可以将父模板与我最初的示例一样对待:

代码语言:javascript
复制
>>> enode = toy.nodelist[0]
>>> enode.parent_name
u'mysite/toyparent.html'
>>> parent = enode.get_parent(enode.parent_name)
>>> parent
<django.template.Template object at 0x101c43790>
>>> parent.nodelist.get_nodes_by_type(VariableNode)
[<Variable Node: adjective>]

还有从父模板中提取的adjective变量。要对ExtendsNode执行测试,可以从django.template.loader_tags导入类

代码语言:javascript
复制
>>> from django.template.loader_tags import ExtendsNode
>>> ext = toy.nodelist.get_nodes_by_type(ExtendsNode)
>>> ext
[<ExtendsNode: extends "mysite/toyparent.html">]

因此,您可以针对模板进行一些测试,以确定是否存在ExtendsNode,然后返回到父模板,并单独获取这些变量名。然而,这开始看起来像一罐蠕虫。

例如,如果要这样做:

代码语言:javascript
复制
>>> toy.nodelist.get_nodes_by_type((ExtendsNode, VariableNode))
[<ExtendsNode: extends "mysite/toyparent.html">, <Variable Node: block.super>, <Variable Node: verb>]

现在,您已经拥有了ExtendsNodeVariableNode对象,并且它开始变得混乱起来。那我们怎么办?我们是否试图忽略从这些测试中返回的任何block变量?我不知道!!

无论如何,这是你想要的信息,但我不认为这是一个实际的解决方案。我坚持认为,也许还有更好的办法。也许值得研究一下你想要解决的问题,看看你是否可以采取另一种方法。

票数 20
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1843324

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档