无法从html/template Golang访问数据。

huangapple go评论93阅读模式
英文:

Can't access data from html/template Golang

问题

我有三个连接的模板:base.htmlmenu.htmlusers.html。但是当我执行这些模板时,我只能从base.html中访问上下文数据。

这是我的处理程序:

func HandlerUser(res http.ResponseWriter, req *http.Request){
    if req.Method == "GET" {
        context := Context{Title: "Users"}
        users,err:= GetUser(0)
        context.Data=map[string]interface{}{
            "users": users,
        }
        fmt.Println(context.Data)
        t,err := template.ParseFiles("public/base.html")
        t,err = t.ParseFiles("public/menu.html")
        t,err = t.ParseFiles("public/users.html")
        err = t.Execute(res,context)
        fmt.Println(err)
    }
}

这是我想在用户模板中显示的内容:

{{ range $user := index .Data "users" }}
<tr id="user-{{ .Id }}">
    <td id="cellId" >{{ $user.Id }}</td>
    <td id="cellUserName" >{{ $user.UserName }}</td>
</tr>
{{ end }}

注意:我可以访问在base.html模板中使用的{{.Title}}

英文:

I have three concatenated templates. base.html, menu.html, users.html. But when I execute these templates I can access data of context only from base.html.

Here is my Handler:

func HandlerUser(res http.ResponseWriter, req *http.Request){
if req.Method == &quot;GET&quot; {
	context := Context{Title: &quot;Users&quot;}
	users,err:= GetUser(0)
	context.Data=map[string]interface{}{
		&quot;users&quot;: users,
	}
	fmt.Println(context.Data)
	t,err := template.ParseFiles(&quot;public/base.html&quot;)
	t,err = t.ParseFiles(&quot;public/menu.html&quot;)
	t,err = t.ParseFiles(&quot;public/users.html&quot;)
	err = t.Execute(res,context)
	fmt.Println(err)
 }
}

This is what I want to show in users template

{{ range $user := index .Data &quot;users&quot; }}
&lt;tr id=&quot;user-{{ .Id }}&quot;&gt;
    &lt;td id=&quot;cellId&quot; &gt;{{ $user.Id }}&lt;/td&gt;
    &lt;td id=&quot;cellUserName&quot; &gt;{{ $user.UserName }}&lt;/td&gt;
&lt;/tr&gt;
{{ end }}

Note: I can access &quot;{{.Title}}&quot; that is used in base.html template.

答案1

得分: 4

首先,你应该检查Template.ParseFiles()方法返回的错误。你存储了返回的错误,但是你只在最后检查了一次(而且在那之后它被覆盖了3次)。

其次,不要在请求处理程序中解析模板,这会消耗太多时间和资源。在启动时(或首次需求时)进行一次解析即可。详细信息请参见https://stackoverflow.com/questions/28451675/it-takes-too-much-time-when-using-template-package-to-generate-a-dynamic-web-p/28453523#28453523。

接下来,你可以一次解析多个文件,只需在传递给Template.ParseFiles() _函数_时枚举所有文件(有一个方法和一个函数)。

要知道Template.Execute()只执行单个(命名的)模板。你有3个关联的模板,但是你的代码只执行了"base.html"模板。要执行特定的、命名的模板,请使用Template.ExecuteTemplate()。详细信息请参见https://stackoverflow.com/questions/42605373/telling-golang-which-template-to-execute-first/42606082#42606082。

首先,你应该定义模板的结构,决定哪些模板包含其他模板,并执行"wrapper"模板(使用Template.ExecuteTemplate())。当你执行调用/包含另一个模板的模板时,你有可能告诉它要传递给它的执行的值(数据)。当你写{{template "something" .}}时,这意味着你想将当前由dot指向的值传递给名为"something"的模板的执行。了解更多信息,请阅读https://stackoverflow.com/questions/42507958/golang-template-engine-pipelines/42508255#42508255。

要了解更多关于模板关联和内部的信息,请阅读这个答案:https://stackoverflow.com/questions/41176355/go-template-name/41187671#41187671。

所以在你的情况下,我想象"base.html"是包装器、外部模板,它包含了"menu.html""users.html"。所以"base.html"应该包含类似以下的行:

{{template "menu.html" .}}

{{template "users.html" .}}

上述行将调用和包含所提到的模板的结果,并将数据传递给它们的执行,这些数据是传递给"base.html"的(如果dot没有改变)。

使用template.ParseFiles() 函数(而不是方法)解析文件,像这样:

var t *template.Template

func init() {
    var err error
    t, err = template.ParseFiles(
        "public/base.html", "public/menu.html", "public/users.html")
    if err != nil {
        panic(err) // 处理错误
    }
}

在处理程序中这样执行:

err := t.ExecuteTemplate(w, "base.html", context)
英文:

First, you should check errors returned by the Template.ParseFiles() method. You store the returned error, but you only check it at the end (and by then it is overwritten like 3 times).

Next, never parse templates in the request handler, it's too time consuming and resource wasting. Do it once at startup (or on first demand). For details see https://stackoverflow.com/questions/28451675/it-takes-too-much-time-when-using-template-package-to-generate-a-dynamic-web-p/28453523#28453523.

Next, you can parse multiple files at once, just enumerate all when passing to the Template.ParseFiles() function (there is a method and a function).

Know that Template.Execute() only executes a single (named) template. You have 3 associated templates, but only the &quot;base.html&quot; template is executed by your code. To execute a specific, named template, use Template.ExecuteTemplate(). For details, see https://stackoverflow.com/questions/42605373/telling-golang-which-template-to-execute-first/42606082#42606082.

First you should define a structure of your templates, decide which templates include others, and execute the "wrapper" template (using Template.ExecuteTemplate()). When you execute a template that invokes / includes another template, you have the possibility to tell what value (data) you what to pass to its execution. When you write {{template &quot;something&quot; .}}, that means you want to pass the value currently pointed by dot to the execution of the template named &quot;something&quot;. Read more about this: https://stackoverflow.com/questions/42507958/golang-template-engine-pipelines/42508255#42508255.

To learn more about template association and internals, read this answer: https://stackoverflow.com/questions/41176355/go-template-name/41187671#41187671.

So in your case I would imagine that &quot;base.html&quot; is the wrapper, outer template, which includes &quot;menu.html&quot; and &quot;users.html&quot;. So &quot;base.html&quot; should contain lines similar to this:

{{template &quot;menu.html&quot; .}}

{{template &quot;users.html&quot; .}}

The above lines will invoke and include the results of the mentioned templates, passing the data to their execution that was passed to &quot;base.html&quot; (if dot was not changed).

Parse the files using the template.ParseFiles() function (not method) like this:

var t *template.Template

func init() {
    var err error
    t, err = template.ParseFiles(
        &quot;public/base.html&quot;, &quot;public/menu.html&quot;, &quot;public/users.html&quot;)
    if err != nil {
        panic(err) // handle error
    }
}

And execute it like this in your handler:

err := t.ExecuteTemplate(w, &quot;base.html&quot;, context)

huangapple
  • 本文由 发表于 2017年3月6日 20:43:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/42625988.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定