Шаблоны django: включают и расширяют

Я хотел бы предоставить один и тот же контент внутри двух разных базовых файлов.

Итак, я пытаюсь сделать это:

page1.html:

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

page2.html:

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

Проблема заключается в том, что я не могу использовать оба расширения и include. Есть ли способ сделать это? А если нет, то как я могу выполнить вышеуказанное?

commondata.html переопределяет блок, который указан как в base1.html, так и в base2.html

Цель этого - предоставить одну и ту же страницу в формате pdf и html, где форматирование немного отличается. Вышеупомянутый вопрос, хотя и упрощает то, что я пытаюсь сделать, если я могу получить ответ на этот вопрос, он решит мою проблему.

Ответ 1

Когда вы используете тег шаблона extends, вы говорите, что текущий шаблон расширяет другой - это дочерний шаблон, зависящий от родительского шаблона. Django будет рассматривать ваш дочерний шаблон и использовать его содержимое для заполнения родителя.

Все, что вы хотите использовать в дочернем шаблоне, должно быть в пределах блоков, которые Django использует для заполнения родителя. Если вы хотите использовать инструкцию include в этом дочернем шаблоне, вы должны поместить его в блок, чтобы Django мог это понять. В противном случае это просто не имеет смысла, и Джанго не знает, что с ним делать.

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

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

Ответ 2

Из Django docs:

Тег include следует рассматривать как реализацию "рендеринга этого подтема и включить HTML", а не как "проанализировать этот подтема и включить его содержимое, как если бы он был частью родителя". Это означает, что между включенными шаблонами не существует общего состояния - каждый из них является полностью независимым процессом рендеринга.

Итак, Django не захватывает никаких блоков из вашего файла commondata.html и не знает, что делать с отображенными внешними блоками html.

Ответ 3

Это должно сделать трюк для вас: поместите тег include внутри секции блока.

page1.html:

{% extends "base1.html" %}

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

page2.html:

{% extends "base2.html" %}

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

Ответ 4

Больше информации о том, почему он не работает для меня, если он помогает будущим людям:

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

Ответ 5

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

Из документации:

{% extends variable%} использует значение переменной. Если переменная оценивается как строка, Django будет использовать эту строку в качестве имени родительского шаблона. Если переменная оценивается объектом Template, Django будет использовать этот объект в качестве родительского шаблона.

Вместо отдельных "page1.html" и "page2.html" поместите {% extends base_template %} вверху "commondata.html". И затем, на ваш взгляд, определите base_template как "base1.html" или "base2.html".

Ответ 6

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

Ответ 7

Редактировать 10 декабря 2015 г.. Как указано в комментариях, ssi устарела с версии 1.8. Согласно документации:

Этот тег устарел и будет удален в Django 1.10. Вместо этого используйте тег include.


На мой взгляд, правильный (лучший) ответ на этот вопрос - это вопрос из podshumok, так как он объясняет, почему поведение include включается при использовании вместе с наследованием.

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

Пожалуйста, обратитесь к документации для получения дополнительной информации (обязательно проверьте подходящую версию Django в селекторе в нижней правой части страницы).

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 define, который должен быть добавлен в ваши файлы настроек.