Tak to mozliwe. A html.Template
to właściwie zestaw plików szablonów. Jeśli wykonasz zdefiniowany blok w tym zestawie, ma on dostęp do wszystkich innych bloków zdefiniowanych w tym zestawie.
Jeśli samodzielnie tworzysz mapę takich zestawów szablonów, masz w zasadzie taką samą elastyczność, jaką oferuje Jinja / Django. Jedyną różnicą jest to, że plik html / template pakiet nie ma bezpośredniego dostępu do systemu plików, więc musisz samodzielnie przeanalizować i skomponować szablony.
Rozważmy następujący przykład z dwiema różnymi stronami („index.html” i „other.html”), które dziedziczą po „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}}
Oraz poniższa mapa zestawów szablonów:
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"))
Możesz teraz renderować swoją stronę „index.html”, dzwoniąc
tmpl["index.html"].Execute("base", data)
i możesz wyrenderować swoją stronę „other.html”, dzwoniąc
tmpl["other.html"].Execute("base", data)
Dzięki pewnym sztuczkom (np. Spójnej konwencji nazewnictwa plików szablonów) możliwe jest nawet tmpl
automatyczne generowanie mapy.
tmpl["index.html"].ExecuteTemplate(w, "base", data)
.{{ .SomeData }}
nie będą wyświetlane w wewnętrznym szablonie. Zewnętrzna działa.template.ParseFiles("index.html", "base.html")
taktemplate.ParseFiles("base.html", "index.html")
?uwaga, kiedy wykonujesz swój podstawowy szablon, musisz przekazać wartości do szablonów potomnych, tutaj po prostu przekazuję ".", aby wszystko zostało przekazane.
szablon jeden wyświetla {{.}}
{{define "base"}} <html> <div class="container"> {{.}} {{template "content" .}} </div> </body> </html> {{end}}
szablon dwa wyświetla {{.domains}} przekazane do elementu nadrzędnego.
{{define "content"}} {{.domains}} {{end}}
Uwaga, gdybyśmy użyli {{template "content".}} Zamiast {{template "content".}}, Domeny nie byłyby dostępne z szablonu treści.
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) }
źródło
Pracując z innymi pakietami szablonów, obecnie pracuję głównie ze standardowym pakietem html / template, myślę, że byłem naiwny, nie doceniając prostoty, jaką zapewnia, i innych zalet. Stosuję bardzo podobne podejście do akceptowanej odpowiedzi z następującymi zmianami
nie musisz owijać swoich układów dodatkowym
base
szablonem, dla każdego sparsowanego pliku tworzony jest blok szablonu, więc w tym przypadku jest on zbędny, lubię również korzystać z akcji blokowej dostępnej w nowej wersji go, co pozwala na domyślna zawartość bloku na wypadek, gdyby nie podano jej w szablonach podrzędnych// base.html <head>{{block "head" .}} Default Title {{end}}</head> <body>{{block "body" .}} default body {{end}}</body>
a szablony stron mogą być takie same jak
// 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}}
teraz, aby wykonać szablony, musisz to tak nazwać
tmpl["index.html"].ExecuteTemplate(os.Stdout, "base.html", data)
źródło
Użyj Pongo , który jest super zestawem szablonów Go, który obsługuje tagi {{extends}} i {{block}} do dziedziczenia szablonów, tak jak Django.
źródło
Wracałem do tej odpowiedzi od wielu dni, w końcu ugryzłem kulę i napisałem małą warstwę abstrakcji / preprocesor do tego. Zasadniczo:
https://github.com/daemonl/go_sweetpl
źródło