ZetCode

Go pongo2

最后修改时间 2024 年 4 月 11 日

在本文中,我们将展示如何在 Golang 中使用 pongo2 模板引擎处理模板。

模板引擎是一种旨在将模板与数据结合以生成文档的库。模板引擎用于生成大量电子邮件、在源代码预处理中,或用于生成动态 HTML 页面。

模板由静态数据和动态区域组成。动态区域随后会被数据替换。渲染函数随后会将模板与数据结合起来。模板引擎用于将模板与数据模型结合以生成文档。

pongo2 库是一个受 Django 模板引擎启发的 Go 模板引擎。

pongo2 在模板字符串中使用各种分隔符

模板可以从字符串(使用 pongo2.FromString)、文件(使用 pongo2.FromFile)或字节(使用 pongo2.FromBytes)读取。

文档使用 ExecuteExecuteWriterExecuteBytes 函数进行渲染。这些函数接受一个 Context,它向模板提供常量、变量、实例或函数。

Go pongo2.FromString

pongo2.FromString 从字符串读取模板。

main.go
package main

import (
    "fmt"
    "log"

    "github.com/flosch/pongo2/v5"
)

func main() {

    tpl, err := pongo2.FromString("Hello {{ name }}!")

    if err != nil {
        log.Fatal(err)
    }

    res, err := tpl.Execute(pongo2.Context{"name": "John Doe"})

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(res)
}

该示例生成一个简单的文本消息。

tpl, err := pongo2.FromString("Hello {{ name }}!")

要打印的变量放在 {{ }} 括号内。

res, err := tpl.Execute(pongo2.Context{"name": "John Doe"})

我们使用 Execute 渲染最终字符串。在上下文中,我们为 name 变量传递了一个值。

$ go run main.go
Hello John Doe!

main.go
package main

import (
    "fmt"
    "log"

    "github.com/flosch/pongo2/v5"
)

func main() {

    tpl, err := pongo2.FromString("{{ name }} is a {{ occupation }}")

    if err != nil {
        log.Fatal(err)
    }

    name, occupation := "John Doe", "gardener"
    ctx := pongo2.Context{"name": name, "occupation": occupation}

    res, err := tpl.Execute(ctx)

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(res)
}

在此示例中,我们在上下文中传递了两个变量。

$ go run main.go
John Doe is a gardener

Go pongo2.FromFile

使用 pongo2.FromFile 函数,我们从文件读取模板。

message.tpl
{{ name }} is a {{ occupation }}

这是模板文件。

main.go
package main

import (
    "fmt"
    "log"

    "github.com/flosch/pongo2/v5"
)

func main() {

    tpl, err := pongo2.FromFile("message.tpl")

    if err != nil {
        log.Fatal(err)
    }

    name, occupation := "John Doe", "gardener"
    ctx := pongo2.Context{"name": name, "occupation": occupation}

    res, err := tpl.Execute(ctx)

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(res)
}

该示例生成一个简单的消息,同时从文件读取模板。

Go pongo2 for 指令

for 指令用于在模板中迭代数据集合。

words.tpl
{% for word in words -%}
    {{ word }}
{% endfor %}

在模板中,我们使用 for 指令遍历 words 数据结构的元素。`-` 字符会去除空白字符。

main.go
package main

import (
    "fmt"
    "log"

    "github.com/flosch/pongo2/v5"
)

func main() {

    tpl, err := pongo2.FromFile("words.tpl")

    if err != nil {
        log.Fatal(err)
    }

    words := []string{"sky", "blue", "storm", "nice", "barrack", "stone"}

    ctx := pongo2.Context{"words": words}

    res, err := tpl.Execute(ctx)

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(res)
}

在程序中,我们将单词切片传递给模板引擎。我们得到一个单词列表作为输出。

$ go run main.go
sky
blue
storm
nice
barrack
stone

Go pongo2 filter

可以对数据应用过滤器来修改它们。过滤器在 `|` 字符后应用。

words.tpl
{% for word in words -%}
    {{ word }} has {{ word | length }} characters
{% endfor %}

length 过滤器返回字符串的大小。

main.go
package main

import (
    "fmt"
    "log"

    "github.com/flosch/pongo2/v5"
)

func main() {

    tpl, err := pongo2.FromFile("words.tpl")

    if err != nil {
        log.Fatal(err)
    }

    words := []string{"sky", "blue", "storm", "nice", "barrack", "stone"}

    ctx := pongo2.Context{"words": words}

    res, err := tpl.Execute(ctx)

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(res)
}

在程序中,我们将单词切片传递给模板。我们打印每个单词及其大小。

$ go run main.go
sky has 3 characters
blue has 4 characters
storm has 5 characters
nice has 4 characters
barrack has 7 characters
stone has 5 characters

Go pongo2 if 条件

可以使用 if/endif 指令创建条件。

todos.tpl
{% for todo in todos -%}
    {% if todo.Done %}
        {{- todo.Title -}}
    {% endif %}
{% endfor %}

在模板文件中,我们使用 if 指令仅输出已完成的任务。

main.go
package main

import (
    "fmt"
    "log"

    "github.com/flosch/pongo2/v5"
)

type Todo struct {
    Title string
    Done  bool
}

type Data struct {
    Todos []Todo
}

func main() {

    tpl, err := pongo2.FromFile("todos.tpl")

    if err != nil {
        log.Fatal(err)
    }

    todos := []Todo{
        {Title: "Task 1", Done: false},
        {Title: "Task 2", Done: true},
        {Title: "Task 3", Done: true},
        {Title: "Task 4", Done: false},
        {Title: "Task 5", Done: true},
    }

    ctx := pongo2.Context{"todos": todos}

    res, err := tpl.Execute(ctx)

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(res)
}

我们从待办事项切片生成输出。在输出中,我们只包含已完成的任务。

服务器示例

在下一个示例中,我们在服务器应用程序中使用模板。

users.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Users</title>
</head>

<body>
    <table>
        <thead>
            <tr>
                <th>Name</th>
                <th>Occupation</th>
            </tr>
        </thead>
        <tbody>
            {% for user in users %}
            <tr>
                <td>{{ user.Name }} </td>
                <td>{{ user.Occupation }}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
</body>
</html>

输出是一个 HTML 文件。用户显示在 HTML 表格中。

main.go
package main

import (
    "net/http"

    "github.com/flosch/pongo2/v5"
)

type User struct {
    Name       string
    Occupation string
}

var tpl = pongo2.Must(pongo2.FromFile("users.html"))

func usersHandler(w http.ResponseWriter, r *http.Request) {

    users := []User{
        {Name: "John Doe", Occupation: "gardener"},
        {Name: "Roger Roe", Occupation: "driver"},
        {Name: "Peter Smith", Occupation: "teacher"},
    }

    err := tpl.ExecuteWriter(pongo2.Context{"users": users}, w)

    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func main() {

    http.HandleFunc("/users", usersHandler)
    http.ListenAndServe(":8080", nil)
}

Web 服务器为 /users URL 路径返回一个带有用户表的 HTML 页面。

var tpl = pongo2.Must(pongo2.FromFile("index.html"))

pongo2.Must 是一个辅助函数,它在应用程序启动时预编译模板。

err := tpl.ExecuteWriter(pongo2.Context{"users": users}, w)

ExecuteWriter 使用给定的上下文渲染模板,并在成功时将输出写入响应写入器。出错时不写入任何内容;而是返回错误。

来源

Go Pongo2 - Github 页面

在本文中,我们使用第三方 pongo2 模板引擎创建了动态文档。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。至今,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程