How to define temporary variables or use macro functions to organize complex display logic in templates?

When using the Anqi CMS to manage website content, we often encounter scenarios where we need to display complex data or reuse similar layouts.If the display logic in the template is not organized effectively, it will soon become long and difficult to read, and it will also be particularly difficult to maintain.Fortunately, the template engine of AnqiCMS (which supports Django template engine syntax) provides powerful tools such as defining temporary variables and using macro functions, which can help us solve these problems elegantly, making the template code both clear and efficient.

Why do we need more flexible template logic?

Imagine you are building a product showcase page, each product card needs to display the product image, title, price, and a brief description.If each card needs to rewrite the HTML structure and data call logic, then when the design needs fine-tuning, you will have to modify the code in dozens or even hundreds of places.It is even worse if you need to perform intermediate calculations in a complex data loop or extract specific information from a nested data structure. Directly stacking logic can make the template resemble a tangled mess, and any small change might trigger unexpected errors.

At this point, introducing temporary variables and macro functions becomes particularly important. They can help us:

  1. Improve code readability:Break down complex data processing steps and represent intermediate results with meaningful variable names.
  2. Enhance maintainability:Centralize management of repeated display logic, so that a single modification takes effect in multiple places.
  3. Enhance development efficiency:Reduce the time spent on repetitive code writing, focusing on the implementation of business logic.
  4. Optimize performance:Avoid unnecessary repeated data queries or calculations (though this is more on the backend side, clear frontend logic helps with overall optimization).

Define temporary variables: make data accessible.

In the template of AnQi CMS, we can use two main methods to define temporary variables:){% with %}Tags and{% set %}tags. They each have their own focus and can be flexibly selected according to specific needs.

Use{% with %}Tags are used to define temporary variables

{% with %}Tags are mainly used to declare one or more variables within a code block. Their scope is limited to thiswithTag's internal, when the code execution reaches{% endwith %}When, these temporary variables will become invalid. This makes it very suitable for assigning the result of a complex expression to a readable variable, or for{% include %}The template fragment being passed transmits specific context data.

For example, we may need to perform a simple calculation on the price in a product list and then display:

{% for product in productList %}
    {% with originalPrice = product.Price, discountRate = 0.8 %}
        {% set finalPrice = originalPrice * discountRate %}
        <div class="product-card">
            <h3>{{ product.Title }}</h3>
            <p>原价: ¥{{ originalPrice }}</p>
            <p>折扣价: ¥{{ finalPrice | floatformat:2 }}</p> {# 使用过滤器保留两位小数 #}
            <a href="{{ product.Link }}">查看详情</a>
        </div>
    {% endwith %}
{% endfor %}

In this example,originalPriceanddiscountRateVariables are only available in the currentproductLoop internally valid, making the calculation process clearer.

Use{% set %}Use tags to assign variables.

{% set %}Tags are more like direct assignment operations in our everyday programming languages. It allows you to assign the result of an expression to a variable, which is valid in the current template file or the currentblockAll are valid until they are reassigned.{% set %} 通常 used to store a single value, extract a specific attribute from a complex object, or perform some calculations that need to span multiple logical blocks.

Assuming we start from aarchiveDetailThe label fetched multiple images, but only the first one is displayed as the cover image:

{% archiveDetail archiveImages with name="Images" %}
{% if archiveImages %}
    {% set firstImage = archiveImages[0] %} {# 提取数组中的第一个元素 #}
    <div class="article-cover">
        <img src="{{ firstImage }}" alt="文章封面">
    </div>
{% else %}
    <div class="article-cover">
        <img src="{% system with name='SiteLogo' %}" alt="默认封面">
    </div>
{% endif %}

Here,firstImageThe variable stores the address of the first image in the article, which can be used elsewhere in the template without needing to retrieve it again.archiveImagesExtracted from it.

The marvel of macro functions in encapsulating complex logic

When a template has long repeated HTML structures and logic, macro functions (Macro) are your savior.It allows you to define a reusable code block, like a custom template function, accepting parameters and outputting content based on the parameters.This greatly reduces code redundancy and makes the template more modular.

Defining and using macro functions

Using macro functions{% macro %}and{% endmacro %}Use tags to define. You can define the parameters accepted by the macro function after its name, and these parameters can be used like ordinary variables within the macro function.

Assuming we have a universal product card layout that needs to be displayed in multiple places on the website:

{# 定义在 partials/product_card.html 文件中 #}
{% macro render_product_card(product) %}
    <div class="product-card-item">
        <a href="{{ product.Link }}">
            <img src="{{ product.Thumb }}" alt="{{ product.Title }}">
            <h4>{{ product.Title | truncatechars:30 }}</h4>
            <p class="price">¥{{ product.Price | floatformat:2 }}</p>
        </a>
    </div>
{% endmacro %}

Then, in the places where we need to use this product card, we can go through:{% import %}Translate the content of the following JSON array into English: [\{"key":0,"value":"标签导入宏文件,并调用宏函数:"}\]

{# 在 index.html 或 list.html 中使用 #}
{% import "partials/product_card.html" as cards %} {# 导入宏文件并起别名 #}

<div class="latest-products">
    <h2>最新产品</h2>
    <div class="product-grid">
        {% archiveList products with moduleId="2" type="list" limit="8" %}
            {% for item in products %}
                {{ cards.render_product_card(item) }} {# 调用宏函数,并传递产品数据 #}
            {% empty %}
                <p>暂无最新产品。</p>
            {% endfor %}
        {% endarchiveList %}
    </div>
</div>

Through macro functions, we encapsulate the display logic of product cards. Whether a product card needs to be displayed on any page, it only takes one line of code to call, which is concise and unified. If the design of the product card needs to be modified in the future (such as adding a 'Buy Now' button), it only requires a modificationpartials/product_card.htmlThis file, all references to it will be automatically updated, greatly improving maintenance efficiency.

Combined with actual scenarios: making the template more powerful

Combine temporary variables and macro functions to allow us to organize complex display logic more flexibly.For example, on a category list page, we may need to iterate through multiple categories and display the latest few articles under each category.At the same time, the display method of each article can also reuse a macro function.

{% import "partials/article_item.html" as article_macros %} {# 导入文章宏函数 #}

<div class="category-sections">
    {% categoryList mainCategories with moduleId="1" parentId="0" limit="4" %}
        {% for category in mainCategories %}
            <div class="category-section">
                <h2><a href="{{ category.Link }}">{{ category.Title }}</a></h2>
                <div class="article-list">
                    {% archiveList articlesInCategory with categoryId=category.Id type="list" limit="5" %}
                        {% for article in articlesInCategory %}
                            {% with articleDate = stampToDate(article.CreatedTime, "2006-01-02") %} {# 临时变量格式化时间 #}
                                {{ article_macros.render_article_summary(article, articleDate) }} {# 调用宏函数,传递文章数据和格式化后的日期 #}
                            {% endwith %}
                        {% empty %}
                            <p>该分类暂无文章。</p>
                        {% endfor %}
                    {% endarchiveList %}
                </div>
            </div>
        {% endfor %}
    {% endcategoryList %}
</div>

In this more complex scenario,{% set %}and{% with %}Can be used to handle local data in loops,{% macro %}while focusing on defining reusable UI components. Together with,{% include %}and{% extends %}these auxiliary tags