Чи можна мати вкладені шаблони в 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автоматично згенерувати карту.


3
чи можна мати дані за замовчуванням, наприклад, для "голови"?
gregghz

18
Тут я просто додам, що для того, щоб відобразити фактичні шаблони, які мені довелося викликати tmpl["index.html"].ExecuteTemplate(w, "base", data).
hermansc

base.html аналізується і зберігається двічі. Ви також можете використовувати функцію Clone (), як у golang.org/pkg/text/template/#example_Template_share
Маартен О.

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

Зверніть увагу, якщо ми використовували {{шаблон "вміст".}} Замість {{шаблон "вміст".}}, Домени не будуть доступні із шаблону вмісту.

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' до шаблонів.
  • Дозволяє замінити виклики "визначити" (таким чином, можливі значення за замовчуванням для greggory)
  • Дозволяє невизначені виклики "шаблону", вони просто дають порожній рядок
  • Встановлює значення за замовчуванням. у "шаблоні" дзвінки до. батька

https://github.com/daemonl/go_sweetpl

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.