如何在Jinja中过滤词典?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Jinja中过滤词典?相关的知识,希望对你有一定的参考价值。

我有一个包的字典,包名是密钥,一些细节的字典是值:

{
        "php7.1-readline": {
            "latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1", 
            "origins": [
                "ppa.launchpad.net"
            ], 
            "version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1", 
            "www": "http://www.php.net/"
        }, 
        "php7.1-xml": {
            "latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1", 
            "origins": [
                "ppa.launchpad.net"
            ], 
            "version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1", 
            "www": "http://www.php.net/"
        }, 
        "plymouth": {
            "version": "0.8.8-0ubuntu17.1"
        },
    ....
}

我想将上面的内容简化为仅包含其值中包含latest属性的包的字典。

似乎json_query是使用的过滤器,但我无法弄清楚语法。那里的例子似乎都在字典列表上运行,而不是相同的词典......

例如,如果我将上面的字典“管道”到json_query('*.latest'),我会得到实际最新版本的列表:

[
  "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
  "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
  "7.1.6-2~ubuntu14.04.1+deb.sury.org+1"
]

我怎样才能获得整个字典元素呢?

有希望吗?

答案

使用dict2items过滤器added in December 2017,可以使用本机功能:

- debug:
    msg: "{{ dict(pkg | dict2items | json_query('[?value.latest].[key, value.latest]')) }}"

结果:

"msg": {
    "php7.1-readline": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
    "php7.1-xml": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1"
}
另一答案

您不能仅使用Jinja过滤器执行此转换(我认为),但您也可以通过应用一些Ansible逻辑来实现。下面的playbook使用with_dict循环遍历字典中的项目,并从匹配的字典中构建一个新的字典:

- hosts: localhost                                                              
  vars:                                                                         
    packages: {                                                                 
        "php7.1-readline": {                                                    
          "latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",                     
          "origins": [                                                          
            "ppa.launchpad.net"                                                 
          ],                                                                    
          "version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",                    
          "www": "http://www.php.net/"                                          
        },                                                                      
        "php7.1-xml": {                                                         
          "latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",                     
          "origins": [                                                          
            "ppa.launchpad.net"                                                 
          ],                                                                    
          "version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",                    
          "www": "http://www.php.net/"                                          
        },                                                                      
        "plymouth": {                                                           
          "version": "0.8.8-0ubuntu17.1"                                        
        }                                                                       
      }                                                                         

  tasks:                                                                        
    - set_fact:                                                                 
        new_packages: >                                                         
          {{ new_packages|default({})|                                          
                combine({item.key: item.value}) }}                              
      with_dict: "{{ packages }}"                                               
      when: "{{ item.value.latest is defined }}"                                

    - debug:                                                                    
        var: new_packages                                                       
另一答案

您将此问题与https://stackoverflow.com/a/41584889/2795592相关联是正确的。

没有选项可以同时使用json_query操作键和值(从Ansible 2.4.0开始)。

这是补丁json_query.py,支持jq-like to_entries / from_entries函数。你可以把它放到你的剧本附近的./filter_plugins并进行这个查询:

- debug:
    msg: "{{ pkg | json_query('to_entries(@) | [?value.latest].{key:key, value:value.latest} | from_entries(@)')}}"

得到这个结果:

"msg": {
    "php7.1-readline": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
    "php7.1-xml": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1"
}

一旦我有空余时间,我就会让公关安全。

以上是关于如何在Jinja中过滤词典?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Jinja2 自定义过滤器中使用 Python 生成器

在 jinja2 中使用 django 过滤器

如何正确应用 django/jinja2 模板过滤器“转义”和“换行符”?

python 如何使用Markdown作为Jinja2模板中的过滤器,然后直接从模板中提取Markdown Meta属性。假设你

自定义jinja2 过滤器

Jinja2 过滤器用于动态注册模板