In AnQiCMS such an efficient and customizable Go language content management system, the flexibility and maintainability at the template level have always been the focus of developers and operators.Especially when facing the need to dynamically generate complex HTML structures based on backend data, we often ponder how to effectively simplify template logic while ensuring rich and diverse content, and avoid code redundancy?macroLook to see if it can become a 'Swiss Army knife' for simplifying template logic in dynamic HTML structure generation.
macroTag: A 'functional' tool in templates.
In the template design philosophy of AnQi CMS, we have retained many advantages of the Django template engine, providing an intuitive and easy-to-use tag system. Among them,macroTags are like small functions in the template world, allowing you to define a reusable code snippet. You can call it like a function, pass in parameters, and generate specific HTML output.
Imagine when your website needs to display a list of products, article cards, or user comments, these elements may appear repeatedly on multiple pages of the website (such as the homepage, category pages, and search results pages).If you copy code blocks every time, it is not only inefficient, but once you need to modify the style or structure of an element, you have to manually adjust it in all places, which is undoubtedly a nightmare for operation and maintenance.macroThe introduction of tags is to solve such pain points.
macroHow to simplify the dynamic HTML structure?
Implement the DRY principle of 'define once, use everywhere':
macroThe core value lies in its code reusability. You can encapsulate the HTML structure of a specific UI component in amacroAn article card containing images, titles, summaries, and links. ThismacroWill accept a "article object" as a parameter. After that, whenever you need to display an article card on any page, just call thismacroPass in the corresponding article data. This is like defining a function when writing a program, abstracting out general logic, which greatly reduces the repetitive code in template files.For example, we can define a function to render a list item of articles.
macro:{% macro article_item(article) %} <div class="article-card"> <a href="{{ article.Link }}"> {% if article.Thumb %} <img src="{{ article.Thumb }}" alt="{{ article.Title }}"> {% endif %} <h3>{{ article.Title }}</h3> <p>{{ article.Description|truncatechars:100 }}</p> <span>发布日期: {{ stampToDate(article.CreatedTime, "2006-01-02") }}</span> </a> </div> {% endmacro %}Then, on different pages, it only needs to be called simply:
{% for post in archives %} {{ article_item(post) }} {% endfor %}Compared to repeating the above long HTML in each loop, doesn't it feel much cleaner at once?
Improve the readability and maintainability of the template:When a page needs to dynamically generate various types of HTML structures, the main template file tends to become bulky and difficult to understand. By
macroWe can abstract these complex substructures, allowing the main template to focus on the overall layout and data flow, while delegating the specific UI rendering logic tomacro.This makes the template structure clearer, making it easier for developers to understand the functionality of each part and facilitating subsequent maintenance and debugging.macroDefinition, all references to it will be synchronized updated, which greatly reduces the maintenance cost.Promote the thinking of component-based development:
macroLabels encourage us to view UI as independent, composable components. For example, in addition to article cards, you might also need a "comment display"macroor a "product specifications table"macroThis modular thinking mode not only helps to keep the template code neat, but also provides a better bridge for collaboration between frontend development and backend templates.Scope limitation brings higher encapsulation:With
includeTags are different,macroHave a more strict scope.It can only access data passed in through parameters and cannot directly access global variables defined outside of it.macroMore independent, controllable, and easier to perform unit testing (if the template engine supports it).It forces you to think about what actual data each UI component really needs, thus designing more robust and lower coupling templates.
How to better organize and usemacro?
To make full use ofmacroThe advantage, especially in large projects, is that a good organization structure is crucial. The template engine of Anqi CMS supports that.macrodefined in an independent auxiliary file and accessed throughimportTag the template where it needs to be used.
You can create a similarpartials/macros.htmlfile to manage all reusablemacro.
{# partials/macros.html 文件内容 #}
{% macro article_item(article) %}
<div class="article-card">
<a href="{{ article.Link }}">
{% if article.Thumb %}
<img src="{{ article.Thumb }}" alt="{{ article.Title }}">
{% endif %}
<h3>{{ article.Title }}</h3>
<p>{{ article.Description|truncatechars:100 }}</p>
<span>发布日期: {{ stampToDate(article.CreatedTime, "2006-01-02") }}</span>
</a>
</div>
{% endmacro %}
{% macro product_card(product) %}
<div class="product-item">
<a href="{{ product.Link }}">
<img src="{{ product.Logo }}" alt="{{ product.Title }}">
<h4>{{ product.Title }}</h4>
<span class="price">¥{{ product.Price }}</span>
</a>
</div>
{% endmacro %}
Then, in the main template file (for exampleindex.htmlorlist.html), import and use as needed:
{# index.html 文件内容 #}
{% import "partials/macros.html" as ui %} {# 将所有macro导入到ui命名空间下 #}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>我的网站 - {% tdk with name="Title" siteName=true %}</title>
</head>
<body>
<header>...</header>
<main>
<h2>最新文章</h2>
<section class="latest-articles">
{% archiveList articles with type="list" moduleId=1 limit=5 %}
{% for item in articles %}
{{ ui.article_item(item) }} {# 使用ui命名空间下的macro #}
{% empty %}
<p>暂无文章。</p>
{% endfor %}
{% endarchiveList %}
</section>
<h2>热门产品</h2>
<section class="hot-products">
{% archiveList products with type="list" moduleId=2 limit=4 %}
{% for item in products %}
{{ ui.product_card(item) }} {# 使用ui命名空间下的macro #}
{% empty %}
<p>暂无产品。</p>
{% endfor %}
{% endarchiveList %}
</section>
</main>
<footer>...</footer>
</body>
</html>
Passas uiNaming the namespace for imported macro definitions can avoid naming conflicts between different macro files, further enhancing the organization and maintainability of template code.
Summary
There is no doubt that when it comes to dynamically generating HTML structures based on data, AnQi CMS ismacroA tag is an extremely effective and elegant solution.It significantly simplifies template logic by encapsulating repeated UI logic into reusable 'functions', thereby enhancing the code's cleanliness, readability, and maintainability.macroTags, undoubtedly, can greatly facilitate your template development, enabling you to build websites that are easier to manage and more flexible.
Common Questions (FAQ)
macroTags andincludeWhat is the difference between tags?macroTags are more like functions with parameters, having their own local scope and can only access data passed through parameters. This makesmacroStronger encapsulation, more suitable for rendering independent, variable parameter UI components.includeTags are more like simply copying and pasting the content of a template file (or a fragment of it) to the current position; it inherits all the context variables of the current template.includeGenerally used to introduce static or common modules that do not require parameters, such as headers, footers, etc.macroIt is more suitable for dynamic and configurable UI elements.Can I
macroDo you call other security CMS template tags or filters internally?Of course you can.macroThe inner part is a complete template context, you can use various built-in tags provided by Anqi CMS (such asif/for), and data tags (such assystem/contact/categoryDetail) and rich filters. For example, in the article card