如何在Jinja2中从ssluser提取域名更新字典列表的domain键?
问题:从SSL用户列表中提取邮箱域名填充domain字段
我已经把字典列表sslusers中每个字典的domain键设为空字符串""。需要检查每个字典的ssluser字段是否已定义,如果已定义,就从该字段的值中提取邮箱域名来填充domain键。
初始sslusers定义
{% set sslusers= [ { 'ssluser': SSL_VPN_User01, 'sslusercred': SSL_USER_CRED01, 'index': 0, 'domain': "" }, { 'ssluser': SSL_VPN_User02, 'sslusercred': SSL_USER_CRED02, 'index': 1, 'domain': "" }, { 'ssluser': SSL_VPN_User03, 'sslusercred': SSL_USER_CRED03, 'index': 2, 'domain': "" }, { 'ssluser': SSL_VPN_User04, 'sslusercred': SSL_USER_CRED04, 'index': 3, 'domain': "" }, { 'ssluser': SSL_VPN_User05, 'sslusercred': SSL_USER_CRED05, 'index': 4, 'domain': "" }, { 'ssluser': SSL_VPN_User06, 'sslusercred': SSL_USER_CRED06, 'index': 5, 'domain': "" }, { 'ssluser': SSL_VPN_User07, 'sslusercred': SSL_USER_CRED07, 'index': 6, 'domain': "" }, { 'ssluser': SSL_VPN_User08, 'sslusercred': SSL_USER_CRED08, 'index': 7, 'domain': "" }, { 'ssluser': SSL_VPN_User09, 'sslusercred': SSL_USER_CRED09, 'index': 8, 'domain': "" }, { 'ssluser': SSL_VPN_User10, 'sslusercred': SSL_USER_CRED10, 'index': 9, 'domain': "" } ] %}
尝试过程中的问题
我一开始用下面的Jinja2代码尝试实现需求,但遇到两个问题:一是domain_value_new未定义,二是不知道如何更新domain键的值:
{%- for item in sslusers if item.ssluser is defined %} {% set domain_value_old = item.domain %} {% for key, value in item.items() %} {% if key == 'domain' %} {% set domain_value_new = item.domain.split('@') | last %} <update dicts in the list with the new value only for 'domain' key> {% endif %} {% endfor %} {% endfor %}
后来我调整代码解决了变量未定义的问题,但还是不知道怎么完成键值更新:
{%- for item in sslusers if item.ssluser is defined %} {% set domain_value_old = item.domain %} {% set domain_value_new = item.ssluser.split('@') | last %} {% for dict_item in item['domain'] %} <do the thing here> {% endfor %} {% endfor %}
解决方案
在Jinja2中,直接修改循环里的字典元素受限于作用域,这里提供两种可行的实现方式:
方法1:创建新的更新后列表
这种方法不会修改原列表,而是生成一个包含更新后数据的新列表,适合需要保留原数据的场景:
{% set updated_sslusers = [] %} {% for item in sslusers %} {% if item.ssluser is defined and '@' in item.ssluser %} {% set updated_item = item.copy() %} {% set _ = updated_item.update({'domain': item.ssluser.split('@') | last}) %} {% set _ = updated_sslusers.append(updated_item) %} {% else %} {% set _ = updated_sslusers.append(item) %} {% endif %} {% endfor %}
- 说明:
- 先用
copy()复制原字典,避免修改原始数据 - 用
update()方法更新domain字段为提取到的域名 - 使用
{% set _ = ... %}来处理无返回值的操作(Jinja2不允许单独调用方法,需要用变量接收)
- 先用
方法2:使用namespace修改原列表
如果允许直接修改原列表,可以借助namespace突破作用域限制:
{% set ns = namespace() %} {% set ns.sslusers = sslusers %} {% for item in ns.sslusers %} {% if item.ssluser is defined and '@' in item.ssluser %} {% set item.domain = item.ssluser.split('@') | last %} {% endif %} {% endfor %}
- 说明:Jinja2中循环内的变量默认是局部的,通过
namespace创建可修改的容器,就能直接更新原列表里的字典元素。
内容的提问来源于stack exchange,提问作者humbleStrength
相关产品推荐
相关产品推荐

