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.

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 .


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

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.


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


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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.