我正在 Golang+AppEngine 中开发一个基本应用程序,我正在尝试像 Django 一样实现模板继承,到目前为止我有以下代码:
var TmplBasePath = "templates/"
var BasePageTmplPath = []string{TmplBasePath + "base.html"}
type Page struct {
Title string
Ctx appengine.Context
}
func NewPage(r *http.Request, title string) *Page {
return &Page{Title: title}
}
func (p *Page) Display(w http.ResponseWriter, tmplPath string) {
tmplPath = TmplBasePath + tmplPath
tmpl := template.New("PAGE")
tmpl = template.Must(template.ParseFiles(BasePageTmplPath...))
tmpl = template.Must(template.ParseFiles(tmplPath))
if err := tmpl.Execute(w, nil); err != nil {
p.Ctx.Errorf("%v ", err)
}
}
func init() {
http.HandleFunc("/", home)
}
func home(w http.ResponseWriter, r *http.Request) {
p := NewPage(r, "home")
p.Display(w, "index.html")
}
我的模板: 基本.html
{{ define "PAGE"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title> Expat Duka </title>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<div class="starter-template">
{{template "CONTENT" .}}
</div>
</div><!-- /.container -->
</body>
</html>
{{end}}
index.html
{{define "CONTENT"}}
<h1> Welcome to Expat Duka </h1>
{{end}}
页面加载,没有错误,但它是空白的,知道我做错了什么
最佳答案
事先:请注意有一个 template.ParseFiles()
函数并且有一个 Template.ParseFiles()
方法。第一个返回一个新模板,第二个您必须调用已创建的模板,它返回一个关联模板。关联的模板彼此了解,因此如果您已经存储了您调用的方法的模板,则甚至不必存储返回的新模板。
首先这是你的问题:
tmpl := template.New("PAGE")
tmpl = template.Must(template.ParseFiles(BasePageTmplPath...))
tmpl = template.Must(template.ParseFiles(tmplPath))
template.ParseFiles()
返回一个新模板(Must()
仅检查其参数并返回相同的参数)。因此,当您在第一行中创建一个新的(使用 template.New()
)时,您会丢失它,因为在第二行中您使用 ParseFiles()
创建了另一个,并且将其分配给同一个 tmpl
变量。
您再次在第三行中创建一个新的、完全独立的第三个模板,并将其分配给 tmpl
变量。
这3个模板是完全独立的,彼此互不了解!
如果您希望模板相互了解(以便它们可以相互引用/包含),请使用 Template.Parse()
或Template.ParseFiles()
方法如本例所示:
tmpl := template.New("PAGE")
template.Must(tmpl.ParseFiles(BasePageTmplPath...))
template.Must(tmpl.ParseFiles(tmplPath))
现在 tmpl
变量中有多个关联的模板,执行您感兴趣的模板:
if err := tmpl.ExecuteTemplate(w, "index.html", nil); err != nil {
p.Ctx.Errorf("%v ", err)
}
注释:
此外,在处理请求的处理程序中解析模板是非常糟糕的做法,它需要相对较长的时间。每次提供请求时解析和创建模板都会在内存中生成大量值,然后将这些值丢弃(因为它们没有被重用),从而为垃圾收集器提供额外的工作。
在应用程序启动时解析模板,将其存储在变量中,并且只需在请求到来时执行模板。请参阅 this answer了解更多详情。
关于html - 模板继承加载空页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29001256/