如何确保 AnQiCMS 模板在变量为 `nil` 时,不会导致页面渲染错误?

在使用 AnQiCMS 构建网站时,我们经常会遇到模板变量可能为空(nil)的情况。例如,一篇文档可能没有设置缩略图,或者一个自定义字段可能没有填写。如果模板代码没有妥善处理这些潜在的空值,页面在渲染时就可能出现错误,影响用户体验,甚至导致网站部分功能不可用。幸运的是,AnQiCMS 的模板引擎提供了多种机制,帮助我们优雅地处理这些变量为 nil 的情况,确保页面的稳定性和流畅性。

AnQiCMS 的模板语法类似于 Django 模板引擎,它使用双花括号 {{变量}} 来输出变量内容,以及单花括号和百分号 {% 标签 %} 来控制逻辑流程。理解这些基本语法以及如何配合过滤器(filters)和标签(tags)使用,是避免 nil 变量导致渲染错误的关键。

一、使用 if 标签进行条件判断

最直接且有效的方法是使用 if 标签对变量进行条件判断。在 AnQiCMS 模板中,{% if 变量 %} 语法会判断变量是否“有值”。通常,这意味着变量不为 nil、不为空字符串 ""、不为数字 0 或布尔值 false

比如,我们希望显示文章的描述,但有些文章可能没有填写描述。如果直接输出 {{ archive.Description }},当描述为空时,页面可能显示空白,或者在某些严格环境下导致错误。我们可以这样处理:

{% if archive.Description %}
    <p>{{ archive.Description }}</p>
{% else %}
    <p>暂无文章简介。</p>
{% endif %}

如果我们需要确保某个图片字段(如 archive.Logoarchive.Thumb)存在才渲染 <img> 标签,则 if 判断非常实用:

{% if archive.Logo %}
    <img src="{{ archive.Logo }}" alt="{{ archive.Title }}" />
{% else %}
    <!-- 方案一:显示一个默认占位图 -->
    <img src="/static/images/default-logo.png" alt="默认图片" />
    <!-- 方案二:或者干脆不显示图片 -->
{% endif %}

对于布尔类型的变量(例如 item.HasChildren),if 标签也能很好地判断其真假,从而决定是否渲染子元素:

{% if item.HasChildren %}
    <ul>
        <!-- 渲染子分类列表 -->
    </ul>
{% endif %}

通过 {% if not 变量 %} 语句,我们也可以方便地检查变量是否为 nil 或空值,并提供替代内容,例如处理“上一篇/下一篇”文档导航时:

{% prevArchive prev %}
上一篇:
{% if not prev %}
  <span>没有了</span>
{% else %}
  <a href="{{ prev.Link }}">{{ prev.Title }}</a>
{% endif %}
{% endprevArchive %}

二、利用 defaultdefault_if_none 过滤器提供默认值

AnQiCMS 模板引擎提供了 defaultdefault_if_none 过滤器,用于在变量为空时提供一个预设的默认值。这对于在行内(inline)处理变量的空值非常方便。

default 过滤器会在变量为 nil、空字符串 ""、数字 0 或布尔值 false 时提供默认值。例如,如果 archive.Title 为空,我们可以让它显示“无标题文章”:

<h1>{{ archive.Title|default:"无标题文章" }}</h1>

对于图片 src 属性,default 过滤器也能派上用场,确保即便图片路径为空,src 属性也能有一个有效的默认值,避免浏览器显示破损图片图标:

<img src="{{ archive.Thumb|default:"/static/images/placeholder.jpg" }}" alt="{{ archive.Title|default:"文章图片" }}" />

default_if_none 过滤器则更为精确,它只会在变量严格为 nil(即 Go 语言中的 nil 值)时提供默认值。如果变量是空字符串 ""、数字 0 或布尔值 false,但不是 nil,则 default_if_none 不会介入。这在某些需要区分“未设置”和“设置为零/空”的场景中非常有用。

例如,一个数字字段 archive.Price 可能被设置为 0(表示免费),也可能为 nil(表示价格未知)。如果 0 是有效值,而 nil 才需要默认,那么 default_if_none 更合适:

价格:{{ archive.Price|default_if_none:"价格待定" }} 元

三、循环中的 empty 语句处理空列表

当我们需要遍历一个列表(数组或切片)时,如果列表为空,直接使用 {% for %} 循环可能导致页面上没有任何内容显示,用户会感到困惑。AnQiCMS 的 for 循环标签提供了 {% empty %} 语句来解决这个问题。

{% for %} 循环内部使用 {% empty %},当被遍历的列表为空时,{% empty %}{% endfor %} 之间的内容就会被渲染,从而提供友好的提示。

例如,在展示文章列表时:

{% archiveList archives with type="list" limit="10" %}
    {% for item in archives %}
        <li><a href="{{ item.Link }}">{{ item.Title }}</a></li>
    {% empty %}
        <li>目前还没有任何文章。</li>
    {% endfor %}
{% endarchiveList %}

这样,即使 archives 列表是空的,页面也不会出现空白,而是会显示“目前还没有任何文章。”的提示。

四、组合使用:构建更健壮的模板

在实际开发中,我们往往需要将上述策略组合起来使用,以构建更健壮、更不容易出错的模板。

例如,一个内容块可能包含标题、描述和图片。我们希望如果标题或描述存在就显示整个内容块,并且图片有默认值:

”`twig {% if archive.Title or archive.Description %}

<div class="article-summary">
    <h2>{{ archive.Title|default:"最新动态"