Можно ли иметь вложенные шаблоны в Go с помощью стандартной библиотеки?

87

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

Если это невозможно, каковы мои альтернативы. Усы, кажется, - вариант, но не упустил ли я тогда такие приятные тонкие функции, html/templateкак контекстно-зависимое экранирование и т. Д.? Какие еще есть альтернативы?

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

Спасибо за прочтение.

Шри Кадимисетти
источник

Ответы:

132

Да, это возможно. html.TemplateФактически A - это набор файлов шаблонов. Если вы выполняете определенный блок в этом наборе, он имеет доступ ко всем другим блокам, определенным в этом наборе.

Если вы создадите карту таких наборов шаблонов самостоятельно, вы получите в основном такую ​​же гибкость, которую предлагает 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автоматически сгенерировать карту.

tux21b
источник
3
можно ли иметь данные по умолчанию, например, для «головы»?
gregghz 06
18
Я просто добавлю сюда то, что мне пришлось вызывать для визуализации фактических шаблонов tmpl["index.html"].ExecuteTemplate(w, "base", data).
hermansc
base.html анализируется и сохраняется дважды. Вы также можете использовать функцию Clone (), как в golang.org/pkg/text/template/#example_Template_share
Maarten O.
3
У меня возникают проблемы при передаче данных во вложенный шаблон. Данные из {{ .SomeData }}не будут отображаться во внутреннем шаблоне. Наружные работы.
0xAffe
это имеет значение, если template.ParseFiles("index.html", "base.html")есть template.ParseFiles("base.html", "index.html")?
shackra
10

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

первый шаблон отображает {{.}}

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

во втором шаблоне отображается {{.domains}}, переданный в родительский.

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

Обратите внимание: если бы мы использовали {{template "content".}} Вместо {{template "content".}}, Домены не были бы доступны из шаблона содержимого.

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
Передача модели - это деталь, на которой я застрял. ;) Спасибо
Патрик
1
я тоже - Потребовалось немного , чтобы выяснить :)
РОБЕРТ король
1
Какие! Не могу поверить, что крошечная точка в конце заполнителя {{template}} имела такое большое значение! Почему об этом нигде не упоминается в руководствах или даже в официальной документации Go ?? Я ошеломлен ... но также очень рад, что нашел ваш ответ! Спасибо большое, теперь мои шаблоны с несколькими уровнями вложенности работают красиво!
Гвинет Ллевелин
Точно то же самое, что я пытался выяснить!
devforfu
5

поработав с другими пакетами шаблонов, теперь, когда я в основном работаю со стандартным пакетом 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)
аллираза
источник
4

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

Роб
источник
4

Я возвращался к этому ответу в течение нескольких дней, наконец, укусил пулю и написал для этого небольшой слой абстракции / предварительный процессор. Это в основном:

  • Добавляет ключевое слово extends в шаблоны.
  • Позволяет переопределять вызовы 'define' (таким образом, возможны значения по умолчанию для greggory)
  • Разрешает неопределенные вызовы шаблонов, они просто дают пустую строку
  • Устанавливает значение по умолчанию. в "шаблоне" вызывает. родителя

https://github.com/daemonl/go_sweetpl

демон
источник