шаблони джанго: включають і розширюють


108

Я б хотів надати однаковий вміст у двох різних базових файлах.

Тому я намагаюся це зробити:

page1.html:

{% extends "base1.html" %}
{% include "commondata.html" %}

page2.html:

{% extends "base2.html" %} 
{% include "commondata.html" %}

Проблема полягає в тому, що я не можу використовувати як розширення, так і включити. Чи є якийсь спосіб це зробити? А якщо ні, то як я можу досягти сказаного?

commondata.html переосмислює блок, який вказаний і в base1.html, і в base2.html

Метою цього є надання однакової сторінки у форматі pdf та html, де форматування дещо відрізняється. Наведене вище питання хоч і спрощує те, що я намагаюся зробити, якщо я можу отримати відповідь, що це вирішить мою проблему.

Відповіді:


110

Використовуючи тег шаблону розширень, ви говорите, що поточний шаблон розширює інший - що це дочірній шаблон, залежний від батьківського шаблону. Джанго перегляне шаблон дитини та використає його вміст для заповнення батьків.

Все, що ви хочете використовувати в дочірньому шаблоні, повинно бути в межах блоків, які Django використовує для заселення батьків. Якщо ви хочете використовувати оператор include у цьому дочірньому шаблоні, вам потрібно помістити його в блок, щоб Django це зрозуміло. Інакше це просто не має сенсу, і Джанго не знає, що з цим робити.

Документація Django містить кілька дійсно хороших прикладів використання блоків для заміни блоків у батьківському шаблоні.

https://docs.djangoproject.com/en/dev/ref/templates/language/#template-inheritance


1
мій commondata.html в ньому визначений блок. Але це не замінює батьківський блок tempalte ... Якщо замість того, щоб включати, я записую точні дані двічі як у page1.html, так і у page2.html, то, звичайно, це працює. Але я хочу визначити цю спільність на commondata.html.
Чистий громадянин

Здається, це працює, я пам'ятаю, що намагався це зробити, але я, мабуть, мав друк або щось на той час, через що це не працює.
Чистий громадянин

1
дивіться мою відповідь нижче, чому це не спрацювало для мене в перший раз, я залишу вас прийнятою відповіддю, хоча ви відповіли на запитання, яке я задав правильно.
Чистий громадянин

80

З Документів Django:

Тег включення повинен розглядатися як реалізація "візуалізації цього підтембра та включення HTML", а не як "розбір цього підтембра та включення його вмісту, як якщо б він був частиною батьківського". Це означає, що між включеними шаблонами не існує спільного стану - кожен включає цілком незалежний процес візуалізації.

Тож Django не захоплює жодних блоків із вашого commondata.html, і він не знає, що робити з виведеними html-сторонніми блоками.


32

Це має зробити для вас хитрість: поставте включити тег всередині блочного розділу.

page1.html:

{% extends "base1.html" %}

{% block foo %}
   {% include "commondata.html" %}
{% endblock %}

page2.html:

{% extends "base2.html" %}

{% block bar %}
   {% include "commondata.html" %}
{% endblock %}

1
Ідеально. Працює для мене.
Трупти М Панчал

13

Більше інформації про те, чому вона не працювала для мене, якщо вона допомагає майбутнім людям:

Причина, чому це не спрацювало, полягає в тому, що {% include%} у django не любить спеціальних символів, таких як фантастичний апостроф. Дані шаблону, які я намагався включити, були вставлені із слова. Мені довелося видалити всі ці спеціальні символи вручну, а потім це було успішно включено.


3

Ви не можете перетягувати блоки із включеного файлу до дочірнього шаблону, щоб замінити блоки батьківського шаблону. Однак ви можете вказати батьківську змінну та вказати базовий шаблон у контексті.

З документації :

{% extends змінна%} використовує значення змінної. Якщо змінна оцінює рядок, Django використовуватиме цей рядок як ім'я батьківського шаблону. Якщо змінна визначається об'єктом Template, Django використовуватиме цей об'єкт як батьківський шаблон.

Замість окремих "page1.html" та "page2.html" поставте {% extends base_template %}вгорі "commondata.html". А потім, на ваш погляд, визначте, base_templateщо це "base1.html" або "base2.html".


2

Додано для посилання на майбутніх людей, які виявили це через google: Ви можете переглянути тег {% overextend%}, наданий бібліотекою мезоніну для таких випадків.


1

Редагувати 10 грудня 2015 року : Як зазначено в коментарях, ssi застаріла з версії 1.8. Відповідно до документації:

Цей тег застарілий і буде видалений у Django 1.10. Використовуйте замість тегу включення.


На мою думку, правильна (найкраща) відповідь на це питання - це відповідь з підшумок , оскільки вона пояснює, чому поведінку включають при використанні разом із спадщиною.

Однак я був дещо здивований, що ніхто не згадував теги ssi, передбачені системою шаблонів Django, яка спеціально розроблена для вбудованого тексту, включаючи зовнішній фрагмент тексту . Тут Inline означає, що зовнішній текст не буде інтерпретуватися, розбиратися чи інтерполюватися, а просто "копіюється" всередині викличного шаблону.

Будь ласка, зверніться до документації для отримання більш детальної інформації (не забудьте перевірити відповідну версію Джанго в селекторі в нижній правій частині сторінки).

https://docs.djangoproject.com/en/dev/ref/templates/builtins/#ssi

З документації:

ssi
Outputs the contents of a given file into the page.
Like a simple include tag, {% ssi %} includes the contents of another file
 which must be specified using an absolute path  in the current page

Остерігайтеся також наслідків щодо безпеки цієї методики, а також необхідного визначення ALLOWED_INCLUDE_ROOTS, яке потрібно додати до файлів налаштувань.


1
Зауважимо, станом на 1.8, ssi застаріло на користь включати. https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#std:templatetag-include
Тім С.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.