Шаблоны Django: переопределение блоков включенных дочерних шаблонов через расширенный шаблон
Мне интересно, если кто-нибудь знает, как справиться со следующей причудливой структурой шаблона:
### base.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<title> {% block title %} Title of the page {% endblock %} </title>
</head>
<body>
<header>
{% block header %}
{% include "base/header.html" %}
{% endblock header %}
</header>
{% block content %}{% endblock %}
</body>
</html>
### base/header.html
<div id="menu-bar">
{% block nav %}
{% include "base/nav.html" %}
{% endblock %}
</div>
### base/nav.html
<nav id="menu">
<ul>
<li>
<a href="/profile/">My Profile</a>
</li>
<li>
<a href="/favs/">My Favorites</a>
</li>
{% block extra-content %}{% endblock %}
</ul>
</nav>
И суть дела:
### app/somepage.html
{% extends "base.html" %}
{% block content %}
<p>Content is overridden!</p>
{% endblock %}
{% block extra-content %}
<p>This will not show up, though...</p>
{% endblock %}
{% block nav %}
<p>Not even this.</p>
{% endblock %}
Проблема в том, что при расширении шаблона вы можете переопределить только блоки, объявленные только в родительском элементе, но не в его дочерних элементах.
Я полагаю, что мог бы сделать base.html шелухой пустых неиспользуемых вложенных блоков, покрывающих все будущие непредвиденные ситуации, но будет ли даже это корректно переопределять? И это единственный способ?
Если вам интересно, почему у меня есть двунаправленный рабочий процесс включения / расширения вокруг base.html, у меня есть много под-шаблонов, которые я хочу использовать во всем проекте: верхние и нижние колонтитулы, навигация, боковые панели и т. Д. Все они будет согласованным по структуре по всему сайту, но во многих случаях целому подразделению сайта понадобятся только некоторые из этих суб-шаблонов. Моя идея состояла в том, чтобы определить под-шаблоны в папке templates / base и иметь шаблоны /base-type1.html, templates/base-type2.html и т. Д. Для расширения в других местах. Каждый тип будет ссылаться только на необходимые суб-шаблоны и переопределять их для размещения контента по мере необходимости.
3 ответа
Вы можете решить эту проблему, расширив свои включенные в настоящее время шаблоны, а затем включив расширение вместо включенного в настоящее время базового шаблона.
It seems to be little known that you can use the with
Ключевое слово с include
to pass variables into the context of an included template - you can use it to specify includes in the included template:
# base.html
<html>
<body>
{% block header %}{% include "header.html" %}{% endblock %}
</body>
</html>
# header.html
# some stuff here
<div id="header">
<img src="logo.png">
{% include nav_tmpl|default:"navigation.html" %}
</div>
# special_page.html (uses other navigation)
{% extends "base.html" %}
{% block header %}
{% include "header.html" with nav_tmpl="special_nav.html" %}
# you might also want to wrap the include in an 'if' tag if you don't want anything
# included here per default
{% endblock %}
Такой подход избавляет вас по крайней мере от наличия одного дополнительного файла только для перезаписи блока. Вы также можете использовать with
Ключевое слово для передачи значения через большую иерархию включает в себя.
Более короткий вариант решения, предложенного @Bernhard Vallant:
# base.html
<html>
<body>
{% block header %}{% include "header.html" %}{% endblock %}
</body>
</html>
# header.html
# some stuff here
<div id="header">
<img src="logo.png">
{% include nav_tmpl|default:"navigation.html" %}
</div>
# special_page.html (uses other navigation)
{% extends "base.html" %}
{% block header %}
{% with nav_tmpl="special_nav.html" %}
{{ block.super }}
{% endwith %}
{% endblock %}