如何输出动态嵌套的项目符号列表?

How to output dynamically nested bulleted list?

我正在输出北美发生的事件列表,我想按国家/地区和地区对其进行细分。给定以下数据:

CA Event 1, Edmonton, AB, Canada
CA Event 2, Edmonton, AB, Canada
CA Event 3, Burnaby, BC, Canada
BE Event 1, Brussels, NULL, Belgium
US Event 1, Juneau, AK, USA
US Event 2, Birmingham, AL, USA
US Event 3, Silverhill, AL, USA

我想要这样的输出

Canada
    Alberta
        CA Event 1, Edmonton, AB, Canada
        CA Event 2, Edmonton, AB, Canada
    British Columbia
        CA Event 3, Burnaby, BC, Canada
Belgium
    BE Event 1, Brussels, Belgium
USA
    Alaska
        US Event 1, Juneau, AK, USA
    Alabama
        US Event 2, Birmingham, AL, USA
        US Event 3, Silverhill, AL, USA

我目前通过输出嵌套的项目符号列表来完成这项工作,但我正在努力弄清楚如何避免重复的 UL 标签。同样,给定上面的输入数据,所需的 HTML 输出应如下所示:

<h2>Canada</h2>
<h3>Alberta</h3>
<ul>
    <li>CA Event 1, Edmonton, AB, Canada</li>
    <li>CA Event 2, Edmonton, AB, Canada</li>
</ul>
<h3>British Columbia</h3>
<ul>
    <li>CA Event 4, Burnaby, BC, Canada</li>
</ul>

但现在看起来像这样:

<h2>Canada</h2>
<h3>Alberta</h3>
<ul>
    <li>CA Event 1, Edmonton, AB, Canada</li>
</ul>
<ul>
    <li>CA Event 2, Edmonton, AB, Canada</li>
</ul>
<h3>British Columbia</h3>
<ul>
    <li>CA Event 4, Burnaby, BC, Canada</li>
</ul>

这是我的模板代码,它使用 Jinja 模板语言作为 Flask 的一部分,但任何响应都不需要它。我只是不知道如何只在需要时输出 UL 标签。

{% set ns = namespace() %}
{% set ns.country_header = '' %}
{% set ns.region_header = '' %}

{% for convention in context.conventions %}

    {% if ns.country_header != convention.country %}
        {% set ns.country_header = convention.country %}
        <h3>{{ns.country_header}}</h3>
    {% endif %}

    {% if ns.region_header != convention.region %}
        {% set ns.region_header = convention.region %}
        <h4>{{ns.region_header}}</h4>
    {% endif %}

    <ul>
        <li>
            {{convention.name}} – 
            {{convention.city}}, {{convention.region}} {% endif %}
        </li>
    </ul>
{% endfor %}

警告:我不会专门讲这种模板语言,但我会讲逻辑。

啊,扁平记录列表的乐趣。 :/

当区域 header 发生变化时发出 <ul> -- 基本上作为 <h4> 标签的一部分。

在考虑 <h3><h4> 项之前,您必须在循环顶部发出 </ul>,方法是检查是否有任何更改。

作为一种特殊情况,第一次进入循环时必须避免发出 </ul>.

您可以在 endfor 之后发出 </ul>

{% for convention in context.conventions %}
    {% if <<not first record>> %}
      </ul> 
    {% endif %}

    {% if ns.country_header != convention.country %}
        {% set ns.country_header = convention.country %}
        <h3>{{ns.country_header}}</h3>
    {% endif %}

    {% if ns.region_header != convention.region %}
        {% set ns.region_header = convention.region %}
        {% if convention.region != "NULL" %}
        <h4>{{ns.region_header}}</h4>
        {% endif %}
      <ul>
    {% endif %}

        <li>
            {{convention.name}} – 
            {{convention.city}}, {{convention.region}} {% endif %}
        </li>
{% endfor %}
{% if << at least one record >> %}
    </ul>
{% endif %}

注意:我想我在 <li> 块中看到了一个额外的 {% endif %}

注意 2:如果 state/province 与上面 <h3> 的最后一条记录相同,此循环将无法发出 <h4> 记录。想想 "Russia / Georgia"** 和 "USA / Georgia"。为了安全起见,您可能需要清除 <h3> 发射块中的 ns.region_header

** 有人可能会因为称格鲁吉亚是俄罗斯的一部分而骚扰我。但这是我能很快想到的唯一 semi-obvious 示例。

感谢 PaulProgrammer,这就是我想出的。这是为后人完成的代码,但我选择了他的回答作为答案。

{% set ns = namespace() %}
{% set ns.active_country = '' %}
{% set ns.active_region = '' %}
{% set ns.open_ul = False %}

{% for convention in context.conventions %}

    {% if not loop.first and (ns.active_country != convention.country) or (ns.active_region != convention.region) %}
        </ul>
        {% set ns.open_ul = False %}
    {% endif %}

    {% if ns.active_country != convention.country %}
        {% set ns.active_country = convention.country %}
        {% set ns.open_ul = False %}
        <h3>{{ns.active_country}}</h3>
    {% endif %}

    {% if ns.active_region != convention.region %}
        {% set ns.active_region = convention.region %}
        {% if not ns.open_ul %}
            {% set ns.open_ul = False %}
        {% endif %}
        {% if ns.active_region %}
            <h4>{{ns.active_region}}</h4>
        {% endif %}
    {% endif %}

    {% if not ns.open_ul %}
        <ul>
        {% set ns.open_ul = True %}
    {% endif %}

    <li>
        <a href="{{convention.website}}" target="_blank">{{convention.name}}</a> – 
        {{convention.city}}{% if convention.country in ['United States', 'Canada'] %}, {{convention.region[0]}} {% endif %} – 
        {{convention.date_string}}
    </li>

{% endfor %}