关于Python的Jinja条件子句依赖于数据类型

Jinja conditional clause dependent on data type

我正在使用saltstack管理bind9区域文件。以前我使用过这样的支柱数据:

1
2
3
4
5
zones:
  example.com:
    a:
      www1: 1.2.3.4
      www2: 1.2.3.5

以及一个Jinja模板文件(缩进只是为了可读性),如下所示:

1
2
3
4
5
{% if info.a is defined %}
  {% for host, defn in info.a.items() %}
    {{ host }}  IN  A  {{ defn }}
  {% endfor %}
{% endif %}

其中info是上下文变量(zones.example.com上的dict)。

现在,我需要能够为每个记录定义多个IP。在前面的例子中,假设我想循环子域www

1
2
3
4
5
6
7
8
zones:
  example.com:
    a:
      www1: 1.2.3.4
      www2: 1.2.3.5
      www:
        - 1.2.3.4
        - 1.2.3.5

这就要求(在jinja模板中)知道defn之间的区别是一个标量值(表示单个IP地址)或一个列表(表示一组IP地址)。类似:

1
2
3
4
5
6
7
8
9
    {% for host, defn in info.a.items() %}
      {% if DEFN_IS_A_LIST_OBJECT %}
        {% for ip in defn %}
          {{ host }} IN A {{ ip }}
        {% endfor %}
      {% else %}
        {{ host }} IN A {{ defn }}
      {% endif %}
    {% endfor %}

从这条线索,我尝试了if isinstance(defn, list),但我得到:

1
Unable to manage file: Jinja variable 'isinstance' is undefined

我也尝试过if len(defn),但是意识到length()会对字符串和列表做出正确的响应。但也报告为错误:

1
Unable to manage file: Jinja variable 'len' is undefined

我如何区分金贾的单子和字符串?


如果该值只能是一个字符串或列表,您可以检查它是否不是带有内置测试的字符串。

1
2
3
4
5
{% if defn is not string %}
    {% for ip in defn %}
        {{ host }} IN A {{ ip }}
    {% endfor %}
{% else %}