猿问

更新嵌套模板 Golang

我正在尝试动态更改内容。但内容保持不变。似乎要获取第一场比赛。不管模板是什么。即使使用硬编码文件名也不起作用。代码按预期工作,但内容无法更改。


主要布局


{{define "layout"}}

    <html>

    <body>

        {{ template "content" }}

    </body>

    </html>

{{end}}

子模板 1


{{ define "content" }}


<h1 style="color: red;">Page 1!</h1>


{{ end }}

子模板 2


{{ define "content" }}


<h1 style="color: blue;">Page 2!</h1>


{{ end }}

围棋代码


package main


import (

    "html/template"

    "net/http"

    "strings"

)


var tpl *template.Template


func init() {

    tpl = template.Must(template.ParseGlob("templates/*.gohtml"))

}


func main() {

    http.HandleFunc("/", index)

    http.ListenAndServe(":8080", nil)

}


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


    path := strings.Trim(r.URL.Path, "/")

    switch path {

    case "":

        path = ("index.gohtml")

    default:

        path = (path + ".gohtml")

    }


    err := tpl.ExecuteTemplate(w, "layout", path)

    if err != nil {

        http.Error(w, err.Error(), http.StatusInternalServerError)

        return

    }

}

我也曾尝试在执行之前执行 ParseFiles,但没有成功。我究竟做错了什么?


浮云间
浏览 122回答 3
3回答

慕运维8079593

我认为,在解析模板后调整路径为时已晚。可行的方法(虽然我不确定这里是否是最优雅的解决方案)是使用以下AddParseTree方法:AddParseTree 为具有给定名称的模板添加解析树并将其与 t 相关联。如果模板尚不存在,它将创建一个新模板。如果模板确实存在,它将被替换。适用于您的情况,根据您将Parse相关模板文件(子模板 1 或 2)的条件,然后在执行之前将其添加到AddParseTreeto 。tpl

慕莱坞森

最后我让它工作了,但只有在不遵循手册的情况下。解决方案第 1 部分跳过模板中的 {{define}} 和 {{end}}。诡异的...<html>  <head>    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">    <title>Go Web Programming</title>  </head>  <body>    layout level    {{ template "content" . }}  </body></html>在子模板中也是如此......<h1 style="color: red;">Page 1!</h1>解决方案第 2 部分我找到了一个带有 AddParsTree 的代码片段,这是代码(经过简化,没有错误处理)package mainimport (    "html/template"    "net/http"    "strings")var tpl *template.Templatefunc init() {    tpl = template.Must(template.ParseGlob("templates/*.html"))}func main() {    http.HandleFunc("/", index)    http.ListenAndServe(":8080", nil)}func index(w http.ResponseWriter, r *http.Request) {    path := strings.Trim(r.URL.Path, "/")    switch path {    case "":        path = ("home.html")    default:        path = (path + ".html")    }    layout := tpl.Lookup("layout.html")    layout, _ = layout.Clone()    t := tpl.Lookup(path)    _, _ = layout.AddParseTree("content", t.Tree)    layout.Execute(w, "")我真的不明白为什么我必须不遵守手册才能让它工作。任何启发我的评论将不胜感激。

料青山看我应如是

我遇到了同样的问题并以这种方式解决了它:这对我来说适用于{{ define "content1" }}...{{ end }}语法,但你必须给你的模板唯一的名称:content1和content2。我制作了一个用于处理模板内容的包。package templatesimport (&nbsp; &nbsp; "html/template"&nbsp; &nbsp; "log"&nbsp; &nbsp; "net/http")var tmpls *template.Template// LoadTemplates parses a template folderfunc LoadTemplates(tmplPath string) {&nbsp; &nbsp; tmpls = template.Must(template.ParseGlob(tmplPath))}// ExecTmpl executes a template and writes itfunc ExecTmpl(w http.ResponseWriter, tmpl string, data interface{}) {&nbsp; &nbsp; tmpls.ExecuteTemplate(w, tmpl, data)}// ExecTmplTree combines and executes two templatesfunc ExecTmplTree(w http.ResponseWriter, outer, inner string, data interface{}) {&nbsp; &nbsp; layout, err := tmpls.Lookup(outer).Clone()&nbsp; &nbsp; if err != nil || layout == nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal("ExecTmplTree: Could not get a copy of template", outer)&nbsp; &nbsp; }&nbsp; &nbsp; content, err := tmpls.Lookup(inner).Clone()&nbsp; &nbsp; if err != nil || content == nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal("ExecTmplTree: Could not get a copy of template", inner)&nbsp; &nbsp; }&nbsp; &nbsp; _, err = layout.AddParseTree("content", content.Tree)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal("ExecTmplTree: Templates could not be combined.")&nbsp; &nbsp; }&nbsp; &nbsp; layout.Execute(w, data)}然后我调用函数如下(在 main.go 或其他地方):// call first to load templates from the folder where your templates are stored// you might need fit the file ending, too, I simply use .html for html-templatesfunc init() {&nbsp; &nbsp; templates.LoadTemplates("web/templates/*.html")}// write a basic template without nestingfunc exampleHandler(w http.ResponseWriter, r *http.Request) {&nbsp; &nbsp; templates.ExecTmplTree(w, "content1", "messageForm", nil)}// write nested templates. here, index is the outer template// and code is the innerfunc indexHandler(w http.ResponseWriter, r *http.Request) {&nbsp; &nbsp; templates.ExecTmplTree(w, "layout", "content1", nil)}
随时随地看视频慕课网APP

相关分类

Go
我要回答