How to define and use macro functions in AnQiCMS templates to create reusable code blocks?

During the process of content creation and publishing, we often encounter some repetitive code snippets, such as the display format of article lists, the layout of product cards, and the specific structure of navigation menus.If you copy code blocks every time, it not only increases the size of the template file and reduces readability, but also brings huge workloads and risk of errors during later modifications.The appearance of macro functions is to solve this pain point, allowing us to encapsulate these reusable code logic and use them flexibly in templates as if calling a function.

AnQiCMS Template Engine and Macro Functions

AnQiCMS uses a template engine syntax similar to Django, which makes it very flexible and easy to learn in template creation.The macro function, as one of its auxiliary tags, is essentially a parameterized template code snippet with an independent scope, handling only the parameters passed in.includethe tags are different,includeThe label inherits and uses all context variables of the current template, while macro functions are more focused on their own received parameters, making macro functions more modular and independent.

Define reusable code blocks: Syntax of macro functions

Macro functions are defined by{% macro macro_name(参数列表) %} ... {% endmacro %}. Structure ofmacro_nameis the name you give to a macro function, and参数列表The variables are the parameters that the macro function needs to receive at runtime, and these variables will be visible and usable within the macro function.The logic inside a macro function can be any valid template code, including HTML structure, other tags, variable output, etc.

For example, we often need to display the brief information of articles at different locations on a website, which may include a title, link, description, and publish date. We can define a macro function for this purpose:

{% macro render_article_item(article) %}
<li class="article-item">
    <a href="{{ article.Link }}" class="article-link">
        <h5 class="article-title">{{ article.Title }}</h5>
    </a>
    <p class="article-description">{{ article.Description|truncatechars:100 }}</p> {# 截取前100字符 #}
    <span class="article-date">{{ stampToDate(article.CreatedTime, "2006-01-02") }}</span>
</li>
{% endmacro %}

in thisrender_article_itemIn a macro function,articleis a parameter passed in, representing a specific article data object. Inside the macro function, it accessesarticleObjects'Link/Title/DescriptionandCreatedTimeUse properties such as 【en】to construct the HTML structure of the article list item. We also used 【en】truncatecharsThe filter extracted the description text and used 【en】stampToDateFunctions formatted the timestamps, all of these are powerful features provided by the AnQiCMS template engine.

Use macros in templates effectively

After defining a macro function, we can call it in the template by{{ macro_name(参数值) }}syntax.

Use macro functions in the same template file.

If a macro function is defined in the current template file, it can be called directly at any needed location within the file. This applies to some local code blocks that are used multiple times within the current template only.

{# 假设render_article_item宏函数已在当前文件顶部定义 #}

<h2>最新文章</h2>
{% archiveList latest_articles with type="list" limit="5" %}
    <ul class="latest-articles-list">
        {% for article in latest_articles %}
            {{ render_article_item(article) }} {# 直接调用宏函数并传入文章对象 #}
        {% endfor %}
    </ul>
{% empty %}
    <p>暂时没有最新文章。</p>
{% endarchiveList %}

Import and use macro functions across template files

To better manage and organize macro functions, it is recommended to define them in separate template files. Typically, these files are stored in a subdirectory of the template directory, for example,partial/macros/This can achieve the global reuse of macro functions and avoid the main template file from becoming too large.

Assuming we have created a file named)macros/common_macros.htmlfile, in which multiple general macro functions are defined, such as:

file:templates/your_template/macros/common_macros.html

{# templates/your_template/macros/common_macros.html #}

{% macro render_article_item(article) %}
<li class="article-item">
    <a href="{{ article.Link }}" class="article-link">
        <h5 class="article-title">{{ article.Title }}</h5>
    </a>
    <p class="article-description">{{ article.Description|truncatechars:100 }}</p>
    <span class="article-date">{{ stampToDate(article.CreatedTime, "2006-01-02") }}</span>
</li>
{% endmacro %}

{% macro render_product_card(product) %}
<div class="product-card">
    <img src="{{ product.Thumb }}" alt="{{ product.Title }}">
    <h3><a href="{{ product.Link }}">{{ product.Title }}</a></h3>
    <p class="product-price">${{ product.Price | floatformat:2 }}</p> {# 格式化价格为两位小数 #}
    <button class="add-to-cart">加入购物车</button>
</div>
{% endmacro %}

Now, in any template file that needs to use these macro functions (for exampleindex.htmlordetail.html), we can useimporttags to import them.importThe syntax of the tag is{% import "文件路径" macro_name1, macro_name2 as alias_name, ... %}.asKeywords allow us to set an alias for imported macro functions to avoid naming conflicts or use a more concise name.

file:templates/your_template/index.html

`twig {# templates/your_template/index.html #}

{% import "macros/common_macros.html" render_article_item, render_product_card as product_card_renderer %}

{% extends "base.html" %} {# Assume the page extends from base.html #}

{% block content %}

<section class="latest-news">
    <h2>最新资讯</h2>
    {% archiveList latest_articles with type="list" moduleId="1" limit="3" %} {# 假设文章模型ID为1 #}
        <ul class="latest-articles-list">
            {% for article in latest_articles %}
                {{ render_article_item(article) }} {# 调用导入的文章宏函数 #}
            {% endfor %}
        </ul>
    {% empty %}
        <p>暂无最新资讯。</p>
    {% endarchiveList %}
</section>

<section class="featured-products">
    <h2>热门产品</h2>
    <div class="featured-products-grid">
        {% archiveList featured_products with type="list" moduleId="2" limit="4" %} {# 假设产品模型ID为2 #}
            {% for product in featured_products %}