【问题标题】:Render one template inside another without parsing them every time在另一个模板中渲染一个模板,而无需每次都解析它们
【发布时间】:2015-12-06 19:42:48
【问题描述】:

我有三个这样的模板:

base.html:

<h1>Base.html rendered here</h1>
{{template "content" .}}

view.html:

{{define "content"}}
...
{{end}}

edit.html:

{{define "content"}}
...
{{end}}

我将它们存储在文件夹“模板”中。

我想要的是动态更改将在 {{template "content" .}} 位置呈现的模板,而无需每次都解析。所以我不想要的是这个:

func main() {
   http.HandleFunc("/edit", handlerEdit)
   http.HandleFunc("/view", handlerView)
   http.ListenAndServe(":8080", nil)
}
func handlerView(w http.ResponseWriter, req *http.Request) {
   renderTemplate(w, req, "view")
}

func handlerEdit(w http.ResponseWriter, req *http.Request) {
   renderTemplate(w, req, "edit")
}

func renderTemplate(w http.ResponseWriter, req *http.Request, tmpl    string) {
   templates, err := template.ParseFiles("templates/base.html",  "templates/"+tmpl+".html")
   if err != nil {
       fmt.Println("Something goes wrong ", err)
       return
   }
   someData := &Page{Title: "QWE", Body: []byte("sample body")}
   templates.Execute(w, someData)
}

我正在查看 template.ParseGlobe(),以便做这样的事情

var templates = template.Must(template.ParseGlob("templates/*.html"))
... //and then somthing like this:
err := templates.ExecuteTemplate(w, tmpl+".html", p)

但是 ExecuteTamplate() 只接收一个字符串作为模板的名称。在这种情况下,我如何渲染两个或更多模板?

【问题讨论】:

  • 执行模板到字符串,然后用这个字符串执行第二个模板
  • UPD:你可以在任何模板中使用{{ template "templates/base.html" .}}

标签: go


【解决方案1】:

不要在调用ExecuteTemplate 时直接写入http.ResponseWriter,而是写入字节缓冲区并通过调用template.HTML 调用将其发送到下一个模板。

var b bytes.Buffer

var templates = template.Must(template.ParseGlob("templates/*.html"))

err := templates.ExecuteTemplate(b, templ_1, p)
if err != nil { //handle err }
err := templates.ExecuteTemplate(w, templ_2, template.HTML(b.String()))
if err != nil { //handle err }

如果您要使用未知数量的模板,您可以使用字符串捕获中间步骤:

var strtmp string
err := templates.ExecuteTemplate(b, templ_1, p)
if err != nil { //handle err }

strtemp = b.String()  //store the output
b.Reset()             //prep buffer for next template's output

err := templates.ExecuteTemplate(b, templ_2, template.HTML(strtmp))
if err != nil { //handle err }

//... until all templates are applied

b.WriteTo(w)  //Send the final output to the ResponseWriter

编辑:正如@Zhuharev 所指出的,如果视图和编辑模板的组成是固定的,那么它们都可以引用基础而不是基础试图提供对视图或编辑的引用:

{{define "viewContent"}}
{{template "templates/base.html" .}}
...Current view.html template...
{{end}}

{{define "editContent"}}
{{template "templates/base.html" .}}
...Current edit.html template...
{{end}}

【讨论】:

  • 我已经尝试按照你说的做,但结果证明我无法使用 ParseGlob() 或 ParseFiles() 解析两个具有相同名称 {{define "content"}} 的模板。我收到“内容”正在重新定义的错误。有一些解决方法吗?朱哈列夫的提议效果很好。
  • Zhuharev 的建议是编写模板的惯用方式。如果您正在处理需要将一个模板传递到另一个模板的动态合成,请在基本模板中定义一个模板,该模板只需将传入的 HTML 放入模板中即可。重命名编辑和视图以避免重复,然后就可以使用了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-12
  • 1970-01-01
  • 2014-07-06
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多