Mako模板变量名
在渲染之前,能不能获取Mako模板中变量的名字呢?
from mako.template import Template
bar = Template("${foo}")
# something like:
# >> print bar.fields()
# ['foo']
使用场景:
我们有一些配置文件,里面指定了从数据库中提取的元数据,这些数据会在网页上显示。客户可以从几百个不同的命名元数据中选择。客户可以配置N个位置,但我们事先并不知道某个特定客户希望在表单中填入哪些元数据。因此,在渲染表单时,我们需要提前知道要传递给这个客户模板的变量名。
我们曾考虑过使用一个包含所有可能值的统一字典,并每次都传递这个字典,但这行不通,因为可供客户选择的元数据字段经常会增加。
因此,我们希望使用Mako来模板化这些配置文件,但我不知道如何确定模板中字段的值,以便构建一个完整的上下文来传递给模板。
2 个回答
0
追踪Mako变量可真没意思。我写了这个小函数来从模板中提取变量——你可以随意使用和改进。
def ListMakoVariables(template):
'''
Extract Mako variables from template.
'''
start = 'XXXX${'
stop = '}YYYY'
makovars = []
splitReady = template.replace('${',start).replace('}',stop)
startParts = splitReady.split('XXXX')
for startStr in startParts:
if '}' in startStr:
makovars.append(startStr.split('YYYY')[0])
vars = set(makovars)
return vars, makovars
顺便说一下,Mako变量是有顺序的,而普通变量是唯一的但没有顺序。
3
不幸的是,从模板对象中获取变量名称并没有简单的方法。
幸运的是,有一个叫做 mako.codegen._Identifiers
的类,它的唯一目的就是在编译过程中跟踪变量。
不幸的是,这个类隐藏得很深,在 Mako 的 API 里,而且在编译完成后就不见了。
幸运的是,你可以在不需要设置 Mako 编译模板时的所有东西的情况下获取它。你只需要使用 mako.lexer.Lexer
来获取一个解析树。
总之,这里是代码:
from mako import lexer, codegen
lexer = lexer.Lexer("${foo}", '')
node = lexer.parse()
# ^ The node is the root element for the parse tree.
# The tree contains all the data from a template
# needed for the code generation process
# Dummy compiler. _Identifiers class requires one
# but only interested in the reserved_names field
compiler = lambda: None
compiler.reserved_names = set()
identifiers = codegen._Identifiers(compiler, node)
# All template variables can be found found using this
# object but you are probably interested in the
# undeclared variables:
# >>> print identifiers.undeclared
# set(['foo'])