Ist es möglich, verschachtelte Vorlagen in Go mit der Standardbibliothek zu haben?

86

Wie bekomme ich verschachtelte Vorlagen wie Jinja in der Python-Laufzeit? TBC Ich meine, wie kann ich eine Reihe von Vorlagen von einer Basisvorlage erben lassen, indem ich nur Blöcke der Basisvorlagen ablege, wie es Jinja / Django-Vorlagen tun. Ist es möglich, nur html/templatein der Standardbibliothek zu verwenden.

Wenn das nicht möglich ist, welche Alternativen gibt es dann? Schnurrbart scheint eine Option zu sein, aber würde ich dann diese netten subtilen Merkmale html/templatewie das kontextsensitive Entkommen usw. verpassen ? Welche anderen Alternativen gibt es?

(Umgebung: Google App Engin, Go Runtime v1, Dev - Mac OSx Lion)

Danke fürs Lesen.

Sri Kadimisetty
quelle

Antworten:

131

Ja, es ist möglich. A html.Templateist eigentlich eine Reihe von Vorlagendateien. Wenn Sie einen definierten Block in diesem Satz ausführen, hat er Zugriff auf alle anderen in diesem Satz definierten Blöcke.

Wenn Sie selbst eine Karte solcher Vorlagensätze erstellen, haben Sie im Grunde die gleiche Flexibilität, die Jinja / Django bietet. Der einzige Unterschied besteht darin, dass das HTML / Template- Paket keinen direkten Zugriff auf das Dateisystem hat. Sie müssen die Vorlagen also selbst analysieren und erstellen.

Betrachten Sie das folgende Beispiel mit zwei verschiedenen Seiten ("index.html" und "other.html"), die beide von "base.html" erben:

// Content of base.html:
{{define "base"}}<html>
  <head>{{template "head" .}}</head>
  <body>{{template "body" .}}</body>
</html>{{end}}

// 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}}

Und die folgende Karte der Vorlagensätze:

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"))

Sie können jetzt Ihre "index.html" -Seite durch Aufrufen rendern

tmpl["index.html"].Execute("base", data)

und Sie können Ihre "other.html" -Seite durch Aufrufen rendern

tmpl["other.html"].Execute("base", data)

Mit einigen Tricks (z. B. einer konsistenten Namenskonvention Ihrer Vorlagendateien) ist es sogar möglich, die tmplKarte automatisch zu generieren .

tux21b
quelle
3
Ist es möglich, Standarddaten zu haben, zum Beispiel für "Kopf"?
Gregghz
18
Ich füge hier nur das hinzu, um die tatsächlichen Vorlagen zu rendern, die ich aufrufen musste tmpl["index.html"].ExecuteTemplate(w, "base", data).
Hermansc
base.html wird zweimal analysiert und gespeichert. Sie können auch die Clone () -Funktion wie in golang.org/pkg/text/template/#example_Template_share
Maarten O.
3
Ich habe Probleme beim Übergeben von Daten an eine verschachtelte Vorlage. Daten von {{ .SomeData }}werden nicht in der inneren Vorlage angezeigt. Das Äußere funktioniert.
0xAffe
es ist wichtig wenn template.ParseFiles("index.html", "base.html")ist template.ParseFiles("base.html", "index.html")?
Shackra
10

Beachten Sie, wenn Sie Ihre Basisvorlage ausführen, müssen Sie Werte an die untergeordneten Vorlagen übergeben. Hier übergebe ich einfach ".", damit alles weitergegeben wird.

Vorlage eins zeigt {{.}}

{{define "base"}}
<html>
        <div class="container">
            {{.}}
            {{template "content" .}}
        </div>
    </body>
</html>
{{end}}

Vorlage zwei zeigt {{.domains}} an, die an das übergeordnete Element übergeben werden.

{{define "content"}}
{{.domains}}
{{end}}

Beachten Sie, dass bei Verwendung von {{template "content".}} Anstelle von {{template "content".}} Über die Inhaltsvorlage nicht auf .domains zugegriffen werden kann.

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)
    }
Robert King
quelle
5
Das Modell weiterzugeben ist ein Detail, an dem ich festgehalten habe. ;) Danke
Patrick
1
Ich auch - brauchte ein bisschen, um herauszufinden :)
Robert King
1
Was! Ich kann nicht glauben, dass der kleine Punkt am Ende des Platzhalters {{template}} so viel Bedeutung hatte! Warum um alles in der Welt wird das nirgendwo in den Tutorials oder sogar in der offiziellen Go-Dokumentation erwähnt? Ich bin verblüfft ... aber auch sehr froh, Ihre Antwort gefunden zu haben! Vielen Dank, jetzt funktionieren meine Vorlagen mit mehreren Verschachtelungsebenen wunderbar!
Gwyneth Llewelyn
Genau das gleiche, was ich herausfinden wollte!
Devforfu
4

Verwenden Sie Pongo , eine Super-Gruppe von Go-Vorlagen, die genau wie Django die Tags {{erweitert}} und {{blockieren}} für die Vorlagenvererbung unterstützen.

rauben
quelle
4

Ich bin seit Tagen auf diese Antwort zurückgekommen, habe endlich die Kugel gebissen und eine kleine Abstraktionsschicht / einen Vorprozessor dafür geschrieben. Es im Grunde:

  • Fügt Vorlagen das Schlüsselwort "Erweitert" hinzu.
  • Ermöglicht das Überschreiben von "Definieren" -Aufrufen (daher sind Standardwerte für greggory möglich).
  • Ermöglicht nicht definierte "Vorlagen" -Aufrufe, sie geben nur eine leere Zeichenfolge an
  • Legt den Standardwert von fest. in 'Vorlage' ruft an. des Elternteils

https://github.com/daemonl/go_sweetpl

Daemonl
quelle
4

Nachdem ich mit anderen Vorlagenpaketen gearbeitet habe, arbeite ich heute hauptsächlich mit Standard-HTML / Vorlagen-Paketen. Ich glaube, ich war naiv, die Einfachheit und andere Extras nicht zu schätzen. Ich verwende einen sehr ähnlichen Ansatz für akzeptierte Antworten mit folgenden Änderungen

Sie müssen Ihre Layouts nicht mit einer zusätzlichen baseVorlage versehen. Für jede analysierte Datei wird ein Vorlagenblock erstellt. In diesem Fall ist er redundant. Ich verwende auch gerne die Blockaktion, die in der neuen Version von go bereitgestellt wird und die es Ihnen ermöglicht Standardblockinhalt für den Fall, dass Sie keinen in untergeordneten Vorlagen angeben

// base.html
<head>{{block "head" .}} Default Title {{end}}</head>
<body>{{block "body" .}} default body {{end}}</body>

und Sie Seitenvorlagen können die gleichen sein wie

// 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}}

Um nun die Vorlagen auszuführen, müssen Sie sie so aufrufen

tmpl["index.html"].ExecuteTemplate(os.Stdout, "base.html", data)
Allyraza
quelle