How to create reusable template code snippets (macros)?

In the daily content operation of Anqi CMS, we often encounter some interface elements or code structures that need to be reused repeatedly.For example, a standardized article list item, a unified style product display card, or a footer contact with specific layout information.If you always manually write this code, it is not only inefficient but also prone to inconsistent formatting issues.This is when the 'Macro' feature provided by Anqi CMS becomes particularly important, as it allows us to easily create reusable template code snippets, greatly enhancing the efficiency and code quality of template development.

What is a template macro (Macro)?

Macro, in the Anqi CMS template engine (based on Django template syntax), can be understood as a 'function' or 'widget' in the template.They allow us to encapsulate a segment of HTML or code with specific logic and structure, and define some parameters that can be passed into it.When needing to use this code, we simply call the macro as if it were a function and pass the corresponding parameters, and the macro will generate predefined content based on these parameters.

Why use template macros?

Using macros can bring many benefits:

  • Reduce duplicate code (DRY principle): Avoid copying and pasting the same code block in multiple template files, making the template more concise.
  • Improve code maintainabilityOnce the display logic or structure of a macro needs to be adjusted, only the definition file of the macro needs to be modified, and all references to the macro will be automatically updated without the need to modify them one by one.
  • Maintain consistency of page style: By rendering specific UI components through unified macros, it can ensure that the visual and interactive style is consistent throughout the website.
  • Improve development efficiencyOnce the macro definition is completed, subsequent development can directly call it, greatly shortening the development time.

How to create and use macros?

The macro function of AnQi CMS is powerful and flexible, which can be defined and used in a single template file, or split into independent macro files for centralized management and inclusion.

1. Define and use macros in the current template file.

The simplest macro usage is to define it directly at the top of the current template file or at any needed position. The definition of macros uses{% macro %}and{% endmacro %}Label wrapping, and can declare accepted parameters.

Example of macro definition:Suppose we need a unified article list card display style, including article title and link.

{% macro article_card(article) %}
<div class="article-item">
    <h3 class="article-title"><a href="{{ article.Link }}">{{ article.Title }}</a></h3>
    {% if article.Description %}
    <p class="article-description">{{ article.Description }}</p>
    {% endif %}
    <span class="article-date">{{ stampToDate(article.CreatedTime, "2006-01-02") }}</span>
</div>
{% endmacro %}

In this example,article_cardIs the name of the macro,articleIt accepts parameters, and we expect an object containing article information to be passed in.

Example of macro call:In the same template file, after we get the article list data, we can call the macro like this:

{% archiveList articles with type="list" limit="5" %}
    {% for item in articles %}
        {{ article_card(item) }} {# 调用上面定义的宏,传入每篇文章的数据 #}
    {% endfor %}
{% endarchiveList %}

In this way, each article will be rendered uniformlyarticle_cardstyles can be added.

2. Store macros in a dedicated file

When the number of macros increases, or when the same macro needs to be reused in multiple template files, it is recommended to store the macro definitions in a separate file. According to the template conventions of Anqi CMS, such code snippets are usually placed in the root directory of the template.partial/In the catalog.

Step 1: Create a macro file.In your template directory (for example)template/default/), create apartial/directory, and create a file in it, such as_macros.html[An underscore prefix is a common convention, indicating that this is an auxiliary file).

Inpartial/_macros.htmlDefine your macros in the file.

{# partial/_macros.html 内容 #}

{% macro article_card(article) %}
<div class="article-item">
    <h3 class="article-title"><a href="{{ article.Link }}">{{ article.Title }}</a></h3>
    {% if article.Description %}
    <p class="article-description">{{ article.Description }}</p>
    {% endif %}
    <span class="article-date">{{ stampToDate(article.CreatedTime, "2006-01-02") }}</span>
</div>
{% endmacro %}

{% macro product_thumbnail(product) %}
<div class="product-thumb">
    <a href="{{ product.Link }}">
        <img src="{{ product.Thumb }}" alt="{{ product.Title }}" loading="lazy">
        <p class="product-name">{{ product.Title }}</p>
    </a>
</div>
{% endmacro %}

Step 2: Introduce and use the macro in other templates.In your main template file (for exampleindex.htmlordetail.html), use{% import %}tags to include macro files. You can include multiple macros at once, or specify aliases for macros.

{# index.html 内容 #}

{% import "partial/_macros.html" article_card, product_thumbnail as thumb_macro %}

{# ... 页面其他内容 ... #}

<h2>最新文章</h2>
<div class="articles-list">
    {% archiveList latestArticles with type="list" moduleId=1 limit="3" %}
        {% for item in latestArticles %}
            {{ article_card(item) }} {# 调用 article_card 宏 #}
        {% endfor %}
    {% endarchiveList %}
</div>

<h2>推荐产品</h2>
<div class="products-grid">
    {% archiveList featuredProducts with type="list" moduleId=2 limit="4" %}
        {% for item in featuredProducts %}
            {{ thumb_macro(item) }} {# 调用 product_thumbnail 宏的别名 thumb_macro #}
        {% endfor %}
    {% endarchiveList %}
</div>

Pass{% import "partial/_macros.html" article_card, product_thumbnail as thumb_macro %}, we included_macros.htmlfile defined.article_cardandproduct_thumbnailTwo macros. Among,product_thumbnailmacros are assignedthumb_macroaliases for convenience of use in the current template.

The scope of the macro: unlikeincludethe key distinction

It should be noted that macros and{% include %}labels have an essential difference in variable scope.

  • {% include %}: will inherit and can directly access all variables in the parent template it calls.
  • {% macro %}: Has its own independent scope.Can onlyaccess variables passed in explicitly through parameters. This means that if you have a variable in the parent template,global_settingVariable, but if it is not passed as a parameter in the macro, it cannot be accessed directly inside the macroglobal_setting.

This design makes macros more independent and modular, reducing unexpected variable conflicts and enhancing the reusability of macros, as it does not depend on specific external environments.

**Practice

  • Clearly nameThe name of the macro should clearly express its function or the components it renders.
  • Single responsibilityAn macro should only be responsible for rendering a specific component or code snippet, avoiding overly complex functionality.
  • ParameterizedPass all potentially variable elements through parameters to make the macro more flexible.
  • Store agreementsPlace all macro files inpartial/directory for easy management and search.
  • Make good use of aliases: InimportSetting a concise alias for a lengthy macro name improves readability.

By mastering the creation and application of macros, you will be able to carry out security CMS template development more efficiently and elegantly, building high-quality websites with clear structure and easy maintenance.


Common Questions (FAQ)

1. Can the macro access all variables on the current page?Cannot.Macros have their own independent scope, and they can only access variables that are explicitly passed as arguments.If you need to use a variable from the parent template in a macro, you must pass it to the macro as an explicit parameter.

2. Macro andincludeWhat are the essential differences between tags? How should I choose?The main differences lie in variable scope and usage scenarios: *