Возможно ли иметь вложенные шаблоны в Go, используя стандартную библиотеку?

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

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

(Среда: Google App Engin, среда выполнения Go 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 с помощью файла ` . `in {{ template "temp" . }} делает данные доступными для вложенного шаблона - person Juancki; 28.03.2021

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

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

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

Второй шаблон отображает {{.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, поддерживающий {{extends}} и { {block}} для наследования шаблонов, как в Django.

person Rob    schedule 02.04.2013

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

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

https://github.com/daemonl/go_sweetpl

person daemonl    schedule 03.02.2014