使用Go语言中的html/template包进行模板渲染和继承。

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

go - Render html/template with inheritance

问题

我有两个HTML模板,index.html扩展了base.html

base.html的内容如下:

{{ define "base" }}
<html>
<head>
    <meta charset="utf-8">
    <title>{{ template "title" . }}</title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
    <script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="/js/isotope.pkgd.min.js"></script>
    <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
    <link rel="stylesheet" type="text/css" href="/css/style.css">
</head>
<body>
    {{ template "index" . }}
</body>
</html>
{{ end }}

index.html的内容如下:

{{ define "title" }}Homepage{{ end }}
{{ define "index" }}
<div class="wrapper">
    <div class="page-content">
        <div class="container">
            <div class="left">
                <img src="../public/images/img_landing_page_mac.png">
            </div>
            <div class="right">
                <h2 style="font-size: 33px; letter-spacing: 5px">Organize <br>Modern Knowledge<br> for Mankind</h2>
                <p style="font-size: 20px;margin-top: 35px;letter-spacing: 4px">Consume, Colect and Revisit <br>Knowledge at Your Fingertips</p>
                <a href="#" style="margin-top: 80px;display: inline-block;margin-left: -17px"><img src="../public/images/btn_get_chrome.png"></a>
            </div>
        </div>
    </div>
</div>
{{ end }}

当我在浏览器上请求该路径时,应该渲染出页面,使用以下回调处理程序:

func IndexHandler(w http.ResponseWriter, r *http.Request) {
    files := []string{"base", "index"}
    util.RenderTemplate(w, nil, files...)
}

RenderTemplate是一个用于渲染模板的包装函数:

func RenderTemplate(w http.ResponseWriter, data interface{}, tmpl ...string) {
    cwd, _ := os.Getwd()
    files := make([]string, len(tmpl))
    for i, file := range tmpl {
        files[i] = filepath.Join(cwd, "./view/"+file+".html")
    }
    t, err := template.ParseFiles(files...)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    templates := template.Must(t, err)
    err = templates.Execute(w, data)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

我启动服务器后,在浏览器上请求该路径,但是没有任何内容被渲染出来。我漏掉了什么?似乎没有理解继承的概念。

我按照这篇教程尝试使用继承/扩展来渲染模板:

https://elithrar.github.io/article/approximating-html-template-inheritance/

英文:

I have two html templates, with index.html extending base.html

base.html is like this:

{{ define &quot;base&quot; }}
&lt;html&gt;
&lt;head&gt;
	&lt;meta charget=&quot;utf-8&quot;&gt;
	&lt;title&gt;{{ template &quot;title&quot; . }}&lt;/title&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;https://code.jquery.com/jquery-2.2.0.min.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;/js/isotope.pkgd.min.js&quot;&gt;&lt;/script&gt;
	&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css&quot;&gt;
	&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&quot;&gt;
	&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/css/style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
	{{ template &quot;index&quot; . }}
&lt;/body&gt;
&lt;/html&gt;
{{ end }}

And index.html:

{{ define &quot;title&quot; }}Homepage{{ end }}
{{ define &quot;index&quot; }}
&lt;div class=&quot;wrapper&quot;&gt;
	&lt;div class=&quot;page-content&quot;&gt;
		&lt;div class=&quot;container&quot;&gt;
			&lt;div class=&quot;left&quot;&gt;
				&lt;img src=&quot;../public/images/img_landing_page_mac.png&quot;&gt;
			&lt;/div&gt;
			&lt;div class=&quot;right&quot;&gt;
				&lt;h2 style=&quot;font-size: 33px; letter-spacing: 5px&quot;&gt;Organize &lt;br&gt;Modern Knowledge&lt;br&gt; for Mankind&lt;/h2&gt;
				&lt;p style=&quot;font-size: 20px;margin-top: 35px;letter-spacing: 4px&quot;&gt;Consume, Colect and Revisit &lt;br&gt;Knowledge at Your Fingertips&lt;/p&gt;
				&lt;a href=&quot;#&quot; style=&quot;margin-top: 80px;display: inline-block;margin-left: -17px&quot;&gt;&lt;img src=&quot;../public/images/btn_get_chrome.png&quot;&gt;&lt;/a&gt;
			&lt;/div&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/div&gt;
{{ end }}

It should render when requesting path on browser with a callback handler:

func IndexHandler(w http.ResponseWriter,r *http.Request){
	files:=[]string{&quot;base&quot;,&quot;index&quot;}
	util.RenderTemplate(w,nil,files...)
}

RenderTemplate is a wrapper function to render

func RenderTemplate(w http.ResponseWriter,data interface{},tmpl... string){
    cwd,_:=os.Getwd()
    files:=make([]string, len(tmpl))
    for i,file:=range tmpl{
        files[i]=filepath.Join(cwd,&quot;./view/&quot;+file+&quot;.html&quot;)
    }
    t,err:=template.ParseFiles(files...)
    if err!=nil{
        http.Error(w,err.Error(),http.StatusInternalServerError)
        return
    }
    templates:=template.Must(t,err)
    err=templates.Execute(w,data)
    if err!=nil {
        http.Error(w,err.Error(),http.StatusInternalServerError)
    }
}

After I start server, I request that path on browser, but nothing is rendered at all. What am I missing? It seems that no inheritance is comprehended here

I follow this tutorial, trying to render templates with inheritance / extension:

https://elithrar.github.io/article/approximating-html-template-inheritance/

答案1

得分: 3

define 动作不执行模板,只有 templateblock 动作才执行。很可能你只是想从基础模板中删除 define(第一行和最后一行),然后它就会按预期工作。

或者你可以使用 Template.ExecuteTemplate 函数代替 Template.Execute。它接受模板的名称:
err = templates.ExecuteTemplate(w, "base", data)

或者,如果你使用的是 Go1.6 或更新版本,可以尝试使用 block 动作代替 define

另外,请考虑使用 gofmt

英文:

The define action doesn't execute template, only template and block actions do. Most probably you just want to remove define from your base template (first and last lines) and it will work as expected.

Or you can use Template.ExecuteTemplate function instead of Template.Execute. It accepts name of the template:
err = templates.ExecuteTemplate(w, "base", data)

Or if you are using Go1.6 or newer you can try block action instead of define.

On the side note, please, consider using gofmt.

huangapple
  • 本文由 发表于 2016年3月10日 10:49:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/35906683.html
匿名

发表评论

匿名网友

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

确定