Golang-pongo2模板引擎

2025-09-18 来源:胡子哥

官网地址:https://pkg.go.dev/github.com/flosch/pongo2

gin使用:https://gitlab.com/go-box/pongo2gin

服务端的使用这里不写,主要摘抄下模版的使用。

这个库就是Django模板语法的还原,所以语法可以参考https://django.readthedocs.io/en/1.7.x/topics/templates.html

直接看Django模板语法也是可以的,这里摘抄一部分常用的方法。

模板继承

可以设置一个布局模版,然后在子模板中用extends使用
主模板:layout.html
<html lang="en">
<body>
<div>这是公共部分</div>
<div>{% block content %}这里可以在子模板中被覆盖{% endblock %}</div>
</body>
</html>


子模板:extends 导入layout.html,其中的 block content 部分内容会插入到 layout 中的block content标记处
{% extends "layout.html" %}
{% block content %}
    {% for entry in blog_entries %}
    <h2>{{ entry.title }}</h2>
    <p>{{ entry.body }}</p>
    {% endfor %}
{% endblock %}

可以有多个 block,比如:{%- block style %}{% endblock -%}、{%- block script %}{% endblock -%}

include载入公用片段

主页面中的变量,片段中是可以直接使用的
{%- include "../include/footer.html" -%}
{%- include "../include/js.html" -%}
定义变量
{% with title="这是声明给header使用的title" keywords="这是声明给header使用的keywords" %} %}标题:{{title}},关键词:{{keywords}}。{% endwith %}
{% include "partial/header.html" with title="这是声明给header使用的title" keywords="这是声明给header使用的keywords" %}
{% set new_var = "hello" %} "hello"可以是服务端传来的变量

注释

{# 单行注释 #}
{% comment %}
块注释
{% endcomment %}

自定义函数在模版中使用

如:创建一个 utilPongo.go
就是写普通的go函数就可以了,模版中可以直接使用
type PonGoUtil struct{}
func (that PonGoUtil) Md5(str string) string {
    return Md5(str, "")
}
要使用这些自定义方法,服务端需要把Util暴露出来,如:
var ponGoUtil PonGoUtil
DATA := pongo2.Context{
  "Flag": code > 199 && code < 300,
  "Code": code,
  "Data": data,
  "Count": count,
  "Msg": HttpCode(code),
  "Title": TITLE,
  "SeoTitle": seoTitle,
  "Description": DESCRIPTION,
  "Keywords": KEYWORDS,
  "Name": NAME,
  "Tpl": tpl,
  "SysInfo": map[string]interface{}{},
  "Util": ponGoUtil, //模版中就可以使用 Util.Md5("123456") 这样的自定义方法了
  "Ctx": c,
}
c.HTML(200, tpl, DATA) //Gin就是这样输出的

在模板中输出当前时间

{% now "Mon Jan 2 15:04:05 -0700 MST 2006" fake %}
{% now "2006-01-02 15:04" %}

输出:{{ 表达式 }}}

integers and complex expressions
{{ 10-100 }}
{{ -(10-100) }}
{{ -(-(10-100)) }}
{{ -1 * (-(-(10-100))) }}
{{ -1 * (-(-(10-100)) ^ 2) ^ 3 + 3 * (5 - 17) + 1 + 2 }}

floats
{{ 5.5 }}
{{ 5.172841 }}
{{ 5.5 - 1.5 == 4 }}
{{ 5.5 - 1.5 == 4.0 }}

mul/div
{{ 2 * 5 }}
{{ 2 * 5.0 }}
{{ 2 * 0 }}
{{ 2.5 * 5.3 }}
{{ 1/2 }}
{{ 1/2.0 }}
{{ 1/0.000001 }}

logic expressions
{{ !true }}
{{ !(true || false) }}
{{ true || false }}
{{ true or false }}
{{ false or false }}
{{ false || false }}
{{ true && (true && (true && (true && (1 == 1 || false)))) }}

float comparison
{{ 5.5 <= 5.5 }}
{{ 5.5 < 5.5 }}
{{ 5.5 > 5.5 }}
{{ 5.5 >= 5.5 }}

remainders
{{ (simple.number+7)%7 }}
{{ (simple.number+7)%7 == 0 }}
{{ (simple.number+7)%6 }}

in/not in
{{ 5 in simple.intmap }}
{{ 2 in simple.intmap }}
{{ 7 in simple.intmap }}
{{ !(5 in simple.intmap) }}
{{ not(7 in simple.intmap) }}
{{ 1 in simple.multiple_item_list }}
{{ 4 in simple.multiple_item_list }}
{{ !(4 in simple.multiple_item_list) }}
{{ "Hello" in simple.misc_list }}
{{ "Hello2" in simple.misc_list }}
{{ 99 in simple.misc_list }}
{{ False in simple.misc_list }}

issue #48 (associativity for infix operators)
{{ 34/3*3 }}
{{ 10 + 24 / 6 / 2 }}
{{ 6 - 4 - 2 }}

issue #64 (uint comparison with int const)
{{ simple.uint }}
{{ simple.uint == 8 }}
{{ simple.uint == 9 }}
{{ simple.uint >= 8 }}
{{ simple.uint <= 8 }}
{{ simple.uint < 8 }}
{{ simple.uint > 8 }}

{{ "a" + "b" }}
{{ 1 + "a" }}
{{ "a" + "1" }}

{{ simple.func_add(simple.func_add(5, 15), simple.number) + 17 }}
{{ simple.func_add_iface(simple.func_add_iface(5, 15), simple.number) + 17 }}
{{ simple.func_variadic("hello") }}
{{ simple.func_variadic("hello, %s", simple.name) }}
{{ simple.func_variadic("%d + %d %s %d", 5, simple.number, "is", 49) }}
{{ simple.func_variadic_sum_int() }}
{{ simple.func_variadic_sum_int(1) }}
{{ simple.func_variadic_sum_int(1, 19, 185) }}
{{ simple.func_variadic_sum_int2() }}
{{ simple.func_variadic_sum_int2(2) }}
{{ simple.func_variadic_sum_int2(1, 7, 100) }}

{% macro greetings(to, from=simple.name, name2="guest") %}
Greetings to {{ to }} from {{ from }}. Howdy, {% if name2 == "guest" %}anonymous guest{% else %}{{ name2 }}{% endif %}!
{% endmacro %}
{{ greetings() }}
{{ greetings(10) }}
{{ greetings("john") }}
{{ greetings("john", "michelle") }}
{{ greetings("john", "michelle", "johann") }}

{% macro test2(loop, value) %}map[{{ loop.Counter0 }}] = {{ value }}{% endmacro %}
{% for item in simple.misc_list %}
{{ test2(forloop, item) }}{% endfor %}

issue #39 (deactivate auto-escape of macros)
{% macro html_test(name) %}
<p>Hello {{ name }}.</p>
{% endmacro %}
{{ html_test("Max") }}

Importing macros
{% import "macro.helper" imported_macro, imported_macro as renamed_macro, imported_macro as html_test %}
{{ imported_macro("User1") }}
{{ renamed_macro("User2") }}
{{ html_test("Max") }}

Chaining macros{% import "macro2.helper" greeter_macro %}
{{ greeter_macro() }}

extends、block、for

{% extends "base_generic.html" %}
{% block title %}{{ section.title }}{% endblock %}
{% block content %}
    <h1>{{ section.title }}</h1>
    {% for story in story_list %}
    <h2><a href="{{ story.get_absolute_url }}">{{ story.headline|upper }}</a></h2>
    <p>{{ story.tease|truncatewords:"100" }}</p>
   {% endfor %}
{% endblock %}

过滤器filter

{{ name|lower }}  把变量name转为小写字母

{{ bio|truncatewords:30 }}  取bio前30个字符

{{ list|join:", " }} 用逗号和空格连接一个列表

{{ value|default:"nothing" }}  给出变量的默认值

{{ value|length }} 输出length

get_digit 可以获取变量中的数字,指定get_digit的值的话,可以获取倒数第几个数字。

{{ 1234567890|get_digit:0 }}
{{ 1234567890|get_digit }}
{{ 1234567890|get_digit:2 }}
{{ 1234567890|get_digit:"4" }}
{{ 1234567890|get_digit:10 }}
{{ 1234567890|get_digit:15 }}

divisibleby 可以判断一个变量是否可以被整除

{{ 21|divisibleby:3 }}
{{ 21|divisibleby:"3" }}
{{ 21|float|divisibleby:"3" }}
{{ 22|divisibleby:"3" }}
{{ 85|divisibleby:simple.number }}
{{ 84|divisibleby:simple.number }}

{{ value|date:``"2006-01-02 15:04"}}  格式化时间

truncatechars、truncatewords 字符串字符、单词多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾:

{{ value|truncatechars:9}}
{{ value|truncatewords:9}}

truncatechars_html、truncatewords_html 功能类似truncatechars、truncatewords。但是这这2个标签用来处理截取html中的字符串,它不会破坏html结构。一个是按字符截取,一个是按单词截取。截断的字符串将以可翻译的省略号序列(“...”)结尾:

{{ "This is a long test which will be cutted after some chars."|truncatechars_html:25 }}
{{ "This is a long test which will be cutted after some words."|truncatewords_html:5|safe }}

{{ value|upper}}  转大写
{{ value|lower}}  转小写

{{ "hello there!"|capfirst }}   capfirst 可以实现句子首字母大写效果

更多参考:

https://juejin.cn/post/6914484139605377038

https://django.readthedocs.io/en/1.7.x/ref/templates/builtins.html#ref-templates-builtins-filters

for

<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>

for循环中预设的几个变量:

VariableDescription
forloop.Counter The current iteration of the loop (1-indexed)
forloop.Counter0The current iteration of the loop (0-indexed)
forloop.RevcounterThe number of iterations from the end of the loop (1-indexed)
forloop.Revcounter0The number of iterations from the end of the loop (0-indexed)
forloop.FirstTrue if this is the first time through the loop
forloop.Last        True if this is the last time through the loop
forloop.ParentloopFor nested loops, this is the loop surrounding the current one

if、elif、else

判断切片列表 可以直接 用 if athlete_list,此处不需要搞到切片长度

{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
Athletes should be out of the locker room soon!
{% else %}
No athletes.
{% endif %}

autoescape

{% autoescape on %}
{{ body }}
{% endautoescape %}

最新评论

文明人,不要粗鲁哦!