英文:
Can't access data from html/template Golang
问题
我有三个连接的模板:base.html
、menu.html
、users.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 == "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)
}
}
This is what I want to show in users template
{{ range $user := index .Data "users" }}
<tr id="user-{{ .Id }}">
<td id="cellId" >{{ $user.Id }}</td>
<td id="cellUserName" >{{ $user.UserName }}</td>
</tr>
{{ end }}
Note: I can access "{{.Title}}"
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 "base.html"
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 "something" .}}
, that means you want to pass the value currently pointed by dot to the execution of the template named "something"
. 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 "base.html"
is the wrapper, outer template, which includes "menu.html"
and "users.html"
. So "base.html"
should contain lines similar to this:
{{template "menu.html" .}}
{{template "users.html" .}}
The above lines will invoke and include the results of the mentioned templates, passing the data to their execution that was passed to "base.html"
(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(
"public/base.html", "public/menu.html", "public/users.html")
if err != nil {
panic(err) // handle error
}
}
And execute it like this in your handler:
err := t.ExecuteTemplate(w, "base.html", context)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论