Възможно ли е да има вложени шаблони в Go, използвайки стандартната библиотека?

Как да получа вложени шаблони като Jinja в средата за изпълнение на Python. TBC това, което имам предвид, е как мога да имам куп шаблони, наследени от базови шаблони, просто подавайки блокове от базовите шаблони, както прави Jinja/django-templates. Възможно ли е да се използва само html/template в стандартната библиотека.

Ако това не е възможно, какви са моите алтернативи. Мустаците изглеждат опция, но тогава ще пропусна ли онези хубави фини характеристики на html/template като чувствителното към контекста избягване и т.н.? Какви други алтернативи има?

(Среда: Google App Engin, Go runtime v1, Dev - Mac OSx lion)

Благодаря за четенето.


person Sri Kadimisetty    schedule 13.07.2012    source източник


Отговори (5)


Да възможно е. html.Template всъщност е набор от шаблонни файлове. Ако изпълните дефиниран блок в този набор, той има достъп до всички останали блокове, дефинирани в този набор.

Ако създадете карта на такива набори шаблони сами, имате основно същата гъвкавост, която предлага Jinja / Django. Единствената разлика е, че пакетът html/template няма директен достъп до файловата система, така че трябва да анализирате и композирате шаблоните сами.

Разгледайте следния пример с две различни страници ("index.html" и "other.html"), които и двете наследяват от "base.html":

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

И следната карта на наборите от шаблони:

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

Вече можете да визуализирате страницата си "index.html", като се обадите

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

и можете да изобразите вашата страница "other.html", като се обадите

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

С някои трикове (напр. последователна конвенция за именуване на вашите шаблонни файлове) дори е възможно автоматично да генерирате tmpl картата.

person tux21b    schedule 13.07.2012
comment
възможно ли е да има данни по подразбиране, например за главата? - person gregghz; 07.10.2012
comment
Тук само ще добавя, че за да изобразя действителните шаблони, трябваше да извикам tmpl["index.html"].ExecuteTemplate(w, "base", data). - person hermansc; 16.05.2013
comment
base.html се анализира и съхранява два пъти. Можете също да използвате функцията Clone() както в golang.org/pkg/text/template/ #example_Template_share - person Maarten O.; 03.03.2015
comment
Имам проблеми при предаване на данни към вложен шаблон. Данните от {{ .SomeData }} няма да се показват във вътрешния шаблон. Външната работи. - person 0xAffe; 18.02.2016
comment
има ли значение дали template.ParseFiles("index.html", "base.html") е template.ParseFiles("base.html", "index.html")? - person shackra; 14.08.2017
comment
@0xAffe с помощта на ` . ` в {{ template "temp" . }} прави данните достъпни за вложения шаблон - person Juancki; 28.03.2021

забележете, когато изпълнявате основния си шаблон, трябва да предадете стойности на дъщерните шаблони, тук просто предавам ".", така че всичко да бъде предадено.

един шаблон показва {{.}}

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

template two показва {{.domains}}, който е предаден на родителя.

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

Забележете, че ако използвахме {{template "content" .}} вместо {{template "content" .}}, .domains няма да са достъпни от шаблона за съдържание.

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)
    }
person robert king    schedule 30.06.2016
comment
Предаването на модела е детайл, на който бях прикован. ;) Благодаря - person Patrick; 18.10.2016
comment
и аз - отне ми малко време да разбера :) - person robert king; 19.04.2017
comment
Какво! Не мога да повярвам, че имаше толкова много смисъл в малката малка точка в края на контейнера {{template}}! Защо, за бога, това не се споменава никъде в уроците или дори в официалната документация на Go?? Смаян съм... но и много щастлив, че намерих вашия отговор! Благодаря ви много, сега моите шаблони с няколко нива на влагане работят прекрасно! - person Gwyneth Llewelyn; 04.05.2017
comment
Точно същото, което се опитвах да разбера! - person devforfu; 30.01.2020

след като съм работил с други пакети с шаблони, напоследък работя най-вече със стандартен пакет html/template, предполагам, че бях наивен да не оценя простотата, която предоставя, и други екстри. Използвам много подобен подход към приетия отговор със следните промени

не е необходимо да обгръщате оформленията си с допълнителен шаблон base, шаблонен блок се създава за всеки анализиран файл, така че в този случай той е излишен, аз също обичам да използвам действието за блокиране, предоставено в новата версия на go, което ви позволява да имат блоково съдържание по подразбиране, в случай че не предоставите такова в дъщерни шаблони

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

и вашите шаблони за страници могат да бъдат същите като

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

сега, за да изпълните шаблоните, трябва да го наречете така

tmpl["index.html"].ExecuteTemplate(os.Stdout, "base.html", data)
person allyraza    schedule 25.10.2018

Използвайте Pongo, което е супер набор от Go Templates, който поддържа {{extends}} и { {block}} тагове за наследяване на шаблони, точно като Django.

person Rob    schedule 02.04.2013

Връщам се към този отговор от дни, най-накрая ухапах куршума и написах малък абстрактен слой / предварителен процесор за това. Това основно:

  • Добавя ключовата дума „extends“ към шаблоните.
  • Позволява отмяна на извикванията на 'define' (по този начин са възможни стойности по подразбиране за greggory)
  • Позволява недефинирани извиквания на „шаблон“, те просто дават празен низ
  • Задава стойността по подразбиране на . в 'template' се обажда на . на родителя

https://github.com/daemonl/go_sweetpl

person daemonl    schedule 03.02.2014