繁体   English   中英

在 jinja2 中创建和填充字典

[英]Creating and populating a dictionary in jinja2

import jinja2 
from jinja2 import Template

records = [{'a':1,'b':1, 'c':1},{'a':1,'b':1, 'c':1}, {'a':2,'b':1, 'c':1}, {'a':3,'b':1, 'c':1}]    

t = jinja2.Template("""
{% set record_info = dict() %}
{% for item in records %}
{% set key =  str(item['a'])+str(item['b'])+str(item['c']) %}
{% if key in record_info %}
{% set record_info.key += 1 %}
{% else %}
{% set record_info.key = 1 %}
{% endif %}
{% endfor %}
{{record_info}}""")    

这给了我:

Traceback (most recent call last):
  File "<stdin>", line 11, in <module>
  File "/Library/Python/2.7/site-packages/jinja2/environment.py", line 945, in __new__
    return env.from_string(source, template_class=cls)
  File "/Library/Python/2.7/site-packages/jinja2/environment.py", line 880, in from_string
    return cls.from_code(self, self.compile(source), globals, None)
  File "/Library/Python/2.7/site-packages/jinja2/environment.py", line 591, in compile
    self.handle_exception(exc_info, source_hint=source_hint)
  File "/Library/Python/2.7/site-packages/jinja2/environment.py", line 780, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "<unknown>", line 6, in template
jinja2.exceptions.TemplateSyntaxError: expected token 'end of statement block', got '.'

我究竟做错了什么?

我能够这样做,有什么改进吗?

records = [{'a':1,'b':1, 'c':1},{'a':1,'b':1, 'c':1}, {'a':2,'b':1, 'c':1}, {'a':3,'b':1, 'c':1}]    
t = jinja2.Template("""
{% set record_info = dict() %}
{% for item in records %}
{% set key =  item['a'] ~ ':' ~ item['b'] ~ ':' ~ item['c'] %}
{% if key in record_info %}
{% set _dummy = record_info.update( {key: record_info[key]+1 })  %}
{% else %}
{% set _dummy = record_info.update({ key:1 }) %}
{% endif %}
{% endfor %}
{{record_info}}""")    
print t.render(records=records)

{u'1:1:1': 2, u'3:1:1': 1, u'2:1:1': 1}

您可以使用“设置”。

{% set x = my_dict.__setitem__("key", "value") %}

然后您可以使用 my_dict,它将具有更新后的值(不要介意 x,它就在那里,不会引发错误)。 这已经在另一个答案中了,在这里

快速解决方案

现有的答案工作得很好,但既然你要求任何改进,我会尝试。

from jinja2 import Template

records = [{'a':1,'b':1, 'c':1},{'a':1,'b':1, 'c':1}, {'a':2,'b':1, 'c':1}, {'a':3,'b':1, 'c':1}]

t = Template("""
{%- set record_info = dict() %}
{%- for item in records %}
  {%- set key = item['a'] ~ ':' ~ item['b'] ~ ':' ~ item['c'] %}
  {%- do record_info.update({key: 1 if not record_info[key] else record_info[key]+1}) %}
{%- endfor -%}
{{record_info}}""",
extensions=['jinja2.ext.do']
)

print(t.render(records=records))

改进

  • 显示导入——来到这里的一些 SO 用户可能是 Python 的新手,需要完整的上下文
  • 使用 Python3 和print()函数(不是批评——我意识到这是在 2017 年,尽管from __future__也可以)
  • 允许使用do “表达式语句”扩展
  • 使用do而不是设置_dummy变量
  • 使用{%--%}-添加到那些开始/结束标记中,避免所有额外呈现的换行符/空格

其他变化

这些改进是否是主观的——可读性是提高了还是受到了阻碍?

  • 使用内联 if (三元) 来删除else子句

笔记

使用默认值

这一行:

{%- do record_info.update({key: 1 if not record_info[key] else record_info[key]+1}) %}

也可以使用default编写:

{%- do record_info.update({key: (record_info[key] | default(0)) + 1 }) %}

请注意,对现有record_info[key]的检查会通过管道传输到默认值,即使当密钥尚不存在时这是一个错误。

例如,这不起作用:

{%- do record_info.update({key: (record_info[key]+1 | default(1)) }) %}

...因为当它尝试评估record_info[key]+1时, record_info[key]错误没有得到处理。

环境和装载机

文档建议使用Loader ,例如PackageLoader ,它支持模板继承等。 在您的示例中,它看起来像是一个快速设置,因此我将忽略该要求。 请注意,直接使用Template构造函数无论如何都会创建一个共享环境,而没有 Loader 或继承的好处。

如果您使用PackageLoader ,您将有一个包名称和一个名为templates的文件夹用于加载它们。 将模板放在单独的文件中也很好。

为了在没有这些单独文件的情况下快速使用真正的加载器, FunctionLoader很有用。 您可以向函数添加更多模板字符串并按名称返回它们,例如

from jinja2 import Environment, FunctionLoader

records = [{'a':1,'b':1, 'c':1},{'a':1,'b':1, 'c':1}, {'a':2,'b':1, 'c':1}, {'a':3,'b':1, 'c':1}]

def my_template(name: str) -> str:
    if name == 'first_one':
        return """
{%- set record_info = dict() %}
{%- for item in records %}
{%- set key = item['a'] ~ ':' ~ item['b'] ~ ':' ~ item['c'] %}
{%- do record_info.update({key: (record_info[key] | default(0)) + 1}) %}
{%- endfor -%}
{{record_info}}"""
    else:
        return """
"""

jinja_env = Environment(
    loader=FunctionLoader(my_template),
    extensions=['jinja2.ext.do']
)

t = jinja_env.get_template('first_one')

print(t.render(records=records))

我知道它只是为实验设置了一个快速和肮脏的例子,但我认为这是一个更好的样板起点,因为它明确使用了Loaders Environment和加载器,因此可以更容易地扩展,当我不可避免地回到我自己的答案时几年后,当我忘记这一切时,我会感激它:D

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM