【问题标题】:Template inheritance loads empty page模板继承加载空页面
【发布时间】:2015-05-14 02:33:33
【问题描述】:

我正在使用 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")

}

我的模板: base.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}}

页面加载,没有错误,但它是空白的,知道我做错了什么

【问题讨论】:

    标签: html go go-templates


    【解决方案1】:

    事前:请注意有template.ParseFiles()函数和有Template.ParseFiles()方法。第一个返回一个new模板,第二个你必须调用一个已经创建的模板,它返回一个关联模板。关联的模板相互了解,因此如果您已经存储了您调用的方法,您甚至不必存储返回的新模板。


    首先这是你的问题:

    tmpl := template.New("PAGE")
    tmpl = template.Must(template.ParseFiles(BasePageTmplPath...))
    tmpl = template.Must(template.ParseFiles(tmplPath))
    

    template.ParseFiles() 返回一个 new 模板(Must() 只是检查其参数并返回相同)。因此,当您在第一行创建一个新的(使用template.New())时,您会丢失它,因为在第二行中您使用ParseFiles() 创建另一个并将其分配给相同的tmpl 变量。 再次在第 3 行创建一个新的、完全独立的第 3 个模板,并将其分配给 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

    【讨论】:

    • “在应用程序启动时解析模板” - 另一种选择是在第一次使用模板时解析模板,然后将其缓存。这对我来说效果很好。
    猜你喜欢
    • 2013-09-28
    • 1970-01-01
    • 2013-04-15
    • 1970-01-01
    • 2011-09-14
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    相关资源
    最近更新 更多