Шаблоны Django: переопределение блоков включенных дочерних шаблонов через расширенный шаблон - PullRequest
33 голосов
/ 03 апреля 2012

Мне интересно, кто-нибудь знает, как справиться со следующей причудливой структурой шаблонов:

### 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 ]

31 голосов
/ 26 ноября 2013

Кажется малоизвестным, что вы можете использовать ключевое слово with с include для передачи переменных в контекст включенного шаблона - вы можете использовать его для указания включений во включенном шаблон:

# 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 для передачи значения через большую иерархию включений.

11 голосов
/ 28 июня 2014

Более короткий вариант решения , предложенного @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 %}
6 голосов
/ 03 апреля 2012

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

...