如何在 AnQiCMS 模板中有效地使用 `if` 和 `for` 标签进行条件判断和数据循环?

在 AnQiCMS 的模板开发中,iffor 标签无疑是构建动态内容、实现灵活布局的核心工具。它们允许我们根据特定条件展示内容,或高效地循环遍历数据,从而将静态模板转化为功能丰富、响应用户需求的页面。AnQiCMS 采用类似 Django 模板引擎的语法,使得这些操作既直观又强大。

if 标签:实现条件判断的艺术

当您需要根据某个条件决定页面上是否显示某个元素,或者显示不同的内容时,if 标签就派上用场了。它的基本结构非常清晰,可以处理简单的真假判断,也能应对复杂的多分支逻辑。

最简单的形式是检查一个变量是否存在或是否为真:

{% if archive.Thumb %}
    <img src="{{ archive.Thumb }}" alt="{{ archive.Title }}">
{% endif %}

这里,如果文档 archive 存在缩略图 Thumb,那么图片就会被渲染出来。这种判断可以应用于任何变量,例如检查一个列表是否为空、一个字符串是否有内容,或者一个布尔值是否为 true

如果您需要更细致的控制,当条件不满足时提供备选内容,可以使用 else

{% if archive.Thumb %}
    <img src="{{ archive.Thumb }}" alt="{{ archive.Title }}">
{% else %}
    <img src="/static/images/placeholder.png" alt="无图">
{% endif %}

这样,如果文章没有缩略图,我们就可以优雅地显示一个占位符图片。

对于更复杂的场景,例如导航菜单中可能需要区分当前页面、有子菜单的父页面或其他普通页面,if-elif-else 结构就能大显身手:

{% if item.IsCurrent %}
    <li class="nav-item active"><a href="{{ item.Link }}">{{ item.Title }}</a></li>
{% elif item.HasChildren %}
    <li class="nav-item has-dropdown"><a href="{{ item.Link }}">{{ item.Title }}</a></li>
{% else %}
    <li class="nav-item"><a href="{{ item.Link }}">{{ item.Title }}</a></li>
{% endif %}

在这里,item.IsCurrentitem.HasChildren 是导航列表项中常见的布尔属性,分别表示该项是否为当前页面或是否拥有子菜单。通过这样的条件判断,我们可以为不同状态的导航项应用不同的样式或行为。

if 标签支持多种比较运算符,如等于 (==)、不等于 (!=)、大于 (>)、小于 (<)、大于等于 (>=)、小于等于 (<=)。此外,您还可以使用 andor 进行逻辑组合,以及 not 进行逻辑非操作。例如,判断一个数值范围或多个条件同时满足的情况。

for 标签:高效地循环数据

网站的核心通常是内容的列表展示,无论是文章列表、产品列表还是导航菜单,都需要重复地渲染相似的结构。for 标签正是为此而生,它让您可以轻松遍历数组或切片等集合类型的数据。

基本的 for 循环语法如下:

{% for item in archives %}
    <div class="article-card">
        <h3><a href="{{ item.Link }}">{{ item.Title }}</a></h3>
        <p>{{ item.Description }}</p>
        <span>发布时间: {{ stampToDate(item.CreatedTime, "2006-01-02") }}</span>
    </div>
{% endfor %}

在这个例子中,archives 可能是一个通过 archiveList 标签获取到的文章列表。循环中的每个 item 都代表列表中的一个文章对象,我们可以通过 item.Titleitem.Link 等方式访问文章的各种属性。

为了更好地控制循环过程,for 标签还提供了几个实用的内置变量:

  • forloop.Counter: 当前循环的序号,从 1 开始计数。
  • forloop.Revcounter: 剩余的循环次数(包括当前次),从总数倒数计数。

这些变量在需要为循环中的第一项或最后一项应用特殊样式时非常有用:

{% for item in archives %}
    <li class="{% if forloop.Counter == 1 %}first-item{% endif %}">
        <a href="{{ item.Link }}">{{ item.Title }}</a>
    </li>
{% endfor %}

当您从数据库中获取数据时,列表可能有时是空的。为了避免页面出现空白或错误,for 标签提供了一个 empty 子句,当循环的集合为空时,它会执行 empty 中的内容:

{% for item in archives %}
    <div class="article-card">
        <h3><a href="{{ item.Link }}">{{ item.Title }}</a></h3>
    </div>
{% empty %}
    <p>当前没有可用的文章。</p>
{% endfor %}

此外,for 标签还支持 reversedsorted 修饰符,让您可以在模板层面调整循环的顺序。reversed 会将集合倒序遍历,而 sorted 会尝试对集合进行排序(通常针对数字或可比较的字符串)。

{# 倒序显示文章列表 #}
{% for item in archives reversed %}
    ...
{% endfor %}

{# 排序后显示文章列表 #}
{% for item in archives sorted %}
    ...
{% endfor %}

iffor 的组合运用:构建复杂布局

iffor 标签的真正威力在于它们的组合使用。通过嵌套循环或在循环内部添加条件判断,我们可以构建出极其灵活和动态的页面结构。

一个典型的场景是构建多级导航菜单。想象一个主导航,每个主项下可能有子项,而子项可能又关联到某个分类下的文章:

{# 假设 navs 是通过 navList 标签获取到的主导航列表 #}
<ul class="main-nav">
    {% for mainItem in navs %}
        <li class="{% if mainItem.IsCurrent %}active{% endif %}">
            <a href="{{ mainItem.Link }}">{{ mainItem.Title }}</a>
            {% if mainItem.NavList %} {# 检查是否有子导航 #}
                <ul class="sub-nav">
                    {% for subItem in mainItem.NavList %}
                        <li class="{% if subItem.IsCurrent %}active{% endif %}">
                            <a href="{{ subItem.Link }}">{{ subItem.Title }}</a>
                            {% if subItem.PageId > 0 %} {# 假设 PageId 大于0表示关联到分类 #}
                                {% categoryList categories with parentId=subItem.PageId %} {# 获取该分类的子分类 #}
                                    {% if categories %}
                                        <ul class="third-nav">
                                            {% for thirdItem in categories %}
                                                <li><a href="{{ thirdItem.Link }}">{{ thirdItem.Title }}</a></li>
                                            {% endfor %}
                                        </ul>
                                    {% else %}
                                        {# 如果没有子分类,尝试显示该分类下的文档 #}
                                        {% archiveList products with type="list" categoryId=subItem.PageId limit="5" %}
                                            {% if products %}
                                                <ul class="third-nav">
                                                    {% for product in products %}
                                                        <li><a href="{{ product.Link }}">{{ product.Title }}</a></li>
                                                    {% endfor %}
                                                </ul>
                                            {% endif %}
                                        {% endarchiveList %}
                                    {% endif %}
                                {% endcategoryList %}
                            {% endif %}
                        </li>
                    {% endfor %}
                </ul>
            {% endif %}
        </li>
    {% endfor %}
</ul>

这个复杂的例子展示了如何结合 navListcategoryListarchiveList 标签,利用 if 判断导航项是否为当前、是否有子项或关联分类,以及 for 循环嵌套遍历多级结构。通过这样的组合,您可以构建出任何所需的导航或内容展示逻辑。

在模板中处理内容时,特别是像文章详情 item.Content 这样的富文本字段,AnQiCMS 默认会进行 HTML 转义以防止安全问题。如果您确定内容是安全的,并且希望浏览器将其作为 HTML 解析,而不是纯文本,