Sí, es posible. A html.Template
es en realidad un conjunto de archivos de plantilla. Si ejecuta un bloque definido en este conjunto, tiene acceso a todos los demás bloques definidos en este conjunto.
Si crea un mapa de tales conjuntos de plantillas por su cuenta, tiene básicamente la misma flexibilidad que ofrece Jinja / Django. La única diferencia es que el paquete html / template no tiene acceso directo al sistema de archivos, por lo que debe analizar y componer las plantillas por su cuenta.
Considere el siguiente ejemplo con dos páginas diferentes ("index.html" y "other.html") que heredan de "base.html":
{{define "base"}}<html>
<head>{{template "head" .}}</head>
<body>{{template "body" .}}</body>
</html>{{end}}
{{define "head"}}<title>index</title>{{end}}
{{define "body"}}index{{end}}
{{define "head"}}<title>other</title>{{end}}
{{define "body"}}other{{end}}
Y el siguiente mapa de conjuntos de plantillas:
tmpl := make(map[string]*template.Template)
tmpl["index.html"] = template.Must(template.ParseFiles("index.html", "base.html"))
tmpl["other.html"] = template.Must(template.ParseFiles("other.html", "base.html"))
Ahora puede renderizar su página "index.html" llamando
tmpl["index.html"].Execute("base", data)
y puede representar su página "other.html" llamando
tmpl["other.html"].Execute("base", data)
Con algunos trucos (por ejemplo, una convención de nomenclatura coherente de sus archivos de plantilla), incluso es posible generar el tmpl
mapa automáticamente.
tmpl["index.html"].ExecuteTemplate(w, "base", data)
.{{ .SomeData }}
no se mostrarán en la plantilla interna. Las obras exteriores.template.ParseFiles("index.html", "base.html")
estemplate.ParseFiles("base.html", "index.html")
?tenga en cuenta que cuando ejecuta su plantilla base, debe pasar valores a las plantillas secundarias, aquí simplemente paso ".", para que todo se transmita.
la plantilla uno muestra {{.}}
{{define "base"}} <html> <div class="container"> {{.}} {{template "content" .}} </div> </body> </html> {{end}}
la plantilla dos muestra {{.domains}} que se pasa al padre.
{{define "content"}} {{.domains}} {{end}}
Tenga en cuenta que si usamos {{template "content".}} En lugar de {{template "content".}}, Los dominios no serían accesibles desde la plantilla de contenido.
DomainsData := make(map[string]interface{}) DomainsData["domains"] = domains.Domains if err := groupsTemplate.ExecuteTemplate(w, "base", DomainsData); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) }
fuente
Habiendo trabajado con otros paquetes de plantillas, hoy en día trabajo principalmente con el paquete estándar html / template, supongo que fui ingenuo al no apreciar la simplicidad que proporciona y otras ventajas. Utilizo un enfoque muy similar para la respuesta aceptada con los siguientes cambios
no necesita ajustar sus diseños con una
base
plantilla adicional , se crea un bloque de plantilla para cada archivo analizado, por lo que en este caso es redundante, también me gusta usar la acción de bloqueo proporcionada en la nueva versión de go, que le permite tener contenido de bloqueo predeterminado en caso de que no proporcione uno en las plantillas secundarias// base.html <head>{{block "head" .}} Default Title {{end}}</head> <body>{{block "body" .}} default body {{end}}</body>
y sus plantillas de página pueden ser las mismas que
// Content of index.html: {{define "head"}}<title>index</title>{{end}} {{define "body"}}index{{end}} // Content of other.html: {{define "head"}}<title>other</title>{{end}} {{define "body"}}other{{end}}
ahora para ejecutar las plantillas necesitas llamarlo así
tmpl["index.html"].ExecuteTemplate(os.Stdout, "base.html", data)
fuente
Utilice Pongo , que es un superconjunto de plantillas Go que admite las etiquetas {{extensions}} y {{block}} para la herencia de plantillas, al igual que Django.
fuente
He estado volviendo a esta respuesta durante días, finalmente mordí la bala y escribí una pequeña capa de abstracción / preprocesador para esto. Básicamente:
https://github.com/daemonl/go_sweetpl
fuente