如何获取 jinja 2 模板中所有变量的列表
Posted
技术标签:
【中文标题】如何获取 jinja 2 模板中所有变量的列表【英文标题】:How to get list of all variables in jinja 2 templates 【发布时间】:2012-01-05 19:48:27 【问题描述】:我正在尝试获取模板中所有变量和块的列表。我不想创建自己的解析器来查找变量。我尝试使用以下 sn-p。
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('gummi', 'templates'))
template = env.get_template('chat.html')
template.blocks
是字典,其中键是块,如何获取块内的所有变量?
【问题讨论】:
【参考方案1】:由于没有人回答这个问题,我找到了答案
from jinja2 import Environment, PackageLoader, meta
env = Environment(loader=PackageLoader('gummi', 'templates'))
template_source = env.loader.get_source(env, 'page_content.html')
parsed_content = env.parse(template_source)
meta.find_undeclared_variables(parsed_content)
这将产生未声明变量的列表,因为它不会在运行时执行,它将产生所有变量的列表。
注意:这将生成包含使用 include
和 extends
的 html 文件。
【讨论】:
不幸的是没有获取变量的属性(即 something.nested 提供 set(['something']) 我有一个模板,其中包含 properties.env 、 proerties.sys 等变量。当我使用上述函数时,我得到了“属性”,但我有兴趣得到一个更深层次,即properties.env 或properties.sys。有人可以建议吗?【参考方案2】:我也有同样的需求,我编写了一个名为 jinja2schema 的工具。它提供了一种启发式算法,用于从 Jinja2 模板推断类型,也可用于获取所有模板变量的列表,包括嵌套变量。
这是一个简短的例子:
>>> import jinja2
>>> import jinja2schema
>>>
>>> template = '''
... x
... % for y in ys %
... y.nested_field_1
... y.nested_field_2
... % endfor %
... '''
>>> variables = jinja2schema.infer(template)
>>>
>>> variables
'x': <scalar>,
'ys': ['nested_field_1': <scalar>, 'nested_field_2': <scalar>]
>>>
>>> variables.keys()
['x', 'ys']
>>> variables['ys'].item.keys()
['nested_field_2', 'nested_field_1']
【讨论】:
(注意:jinja2schema usesEnvironment.parse
从模板中获取一个AST,然后使用它。)【参考方案3】:
对于我的鹈鹕主题,我创建了一个工具来分析我的模板文件中的所有 jinja 变量。
我分享我的代码
此脚本从模板文件中存在的所有变量生成示例配置,并从我的官方 pelicanconf.py 中获取变量
从模板文件中提取所有变量的函数
def get_variables(filename):
env = Environment(loader=FileSystemLoader('templates'))
template_source = env.loader.get_source(env, filename)[0]
parsed_content = env.parse(template_source)
完整的脚本
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# use:
# generate_pelicanconf-sample.py my_official_blog/pelicanconf.py
import sys
import imp
import os
from jinja2 import Environment, FileSystemLoader, meta
# Search all template files
def list_html_templates():
dirList = os.listdir('templates')
return dirList
# get all variable in template file
def get_variables(filename):
env = Environment(loader=FileSystemLoader('templates'))
template_source = env.loader.get_source(env, filename)[0]
parsed_content = env.parse(template_source)
return meta.find_undeclared_variables(parsed_content)
# Check if the pelicanconf.py is in param
if len(sys.argv) != 2:
print("Please indicate the pelicanconf.py file")
sys.exit()
# Get all vars from templates files
all_vars = set()
files = list_html_templates()
for fname in files:
variables = get_variables(fname)
for var in variables:
if var.isupper():
all_vars.add(var)
m = imp.load_source('pelicanconf', sys.argv[1])
# Show pelicanconf.py vars content
for var in all_vars:
varname = 'm.%s' % var
if var in m.__dict__:
print ("%s = %s" % (var, repr(m.__dict__[var])))
return meta.find_undeclared_variables(parsed_content)
这个程序的示例结果
LINKS = ((u'Home', u'/'), (u'archives', u'/archives.html'), (u'tags', u'/tags.html'), (u'A propos', u'http://bruno.adele.im'))
SITESUBTITLE = u'Une famille compl\xe8tement 633<'
DEFAULT_LANG = u'fr'
SITEURL = u'http://blog.jesuislibre.org'
AUTHOR = u'Bruno Adel\xe9'
SITENAME = u'Famille de geeks'
SOCIAL = ((u'adele', u'http://adele.im'), (u'feed', u'http://feeds.feedburner.com/FamilleDeGeek'), (u'twitter', u'http://twitter.com/jesuislibre.org'), (u'google+', u'https://plus.google.com/100723270029692582967'), (u'blog', u'http://blog.jesuislibre.org'), (u'facebook', u'http://www.facebook.com/bruno.adele'), (u'flickr', u'http://www.flickr.com/photos/b_adele'), (u'linkedin', u'http://fr.linkedin.com/in/brunoadele'))
FEED_DOMAIN = u'http://blog.jesuislibre.org'
FEED_ALL_ATOM = u'feed.atom'
DISQUS_SITENAME = u'blogdejesuislibreorg'
DEFAULT_PAGINATION = 10
GITHUB_BLOG_SITE = u'https://github.com/badele/blog.jesuislibre.org'
有关此脚本的更多详细信息,请参阅https://github.com/badele/pelican-theme-jesuislibre
【讨论】:
【参考方案4】:解决方案: https://gist.github.com/sxslex/822bd2405885294747b86aac187f1aa8
def template(html, **params):
import jinja2
env = jinja2.Environment(loader=FileSystemLoader(''))
def tojson(s):
import json
return json.dumps(s)
env.filters['tojson'] = tojson
template = env.from_string(html)
return template.render(context=params, **params)
print(template(' context|tojson ', name='slex', value=39 ))
【讨论】:
这回答了一个完全不同的问题;即传入了哪些参数。 OP 要求提供模板中使用的名称列表。 这是一个令人震惊的错误方向,整齐地包装在一个函数中。以上是关于如何获取 jinja 2 模板中所有变量的列表的主要内容,如果未能解决你的问题,请参考以下文章