Krystian Cybulski
Krystian Cybulski

Reputation: 11108

Django multi-level template extends and nested blocks

Let's say I have the three html template files shown below. HTML is minimal just to illustrate the point.

Is it possible to somehow nest a block named extra_head_content inside of a block already named extra_head_content. The idea is to allow the third-level template to provide a block named extra_head_content. The template above it takes that content, adds it to its block named extra_head_content and provides this combined block to its parent template.

Essentially, I am looking for block nesting across inherited template files.

The exact scenario I am trying to solve is that any template should be able to add extra javascript or css files to the head element. However, the lowest template should not care how many levels down it is nested. Similarly, the extra head content provided by an intermediate template should not get overwritten by the block element of the terminal template.

base.html

<html>
<head>
    <link rel="stylesheet" type="text/css" href="/static/css/reset.css" />
    {% block extra_head_content %}{% endblock %}
</head>
<body>{% block content %}{% endblock %}
</html>

account.html

{% extends "base.html" %}

{% block extra_head_content  %}
    <link rel="stylesheet" type="text/css" href="/static/css/account.css" />
    {% block extra_head_content  %}{% endblock %}
{% endblock %}

{% block content %}
    <div id="menu">...</div>
    {% block account_content %}{% endblock %}
{% endblock %}

account_profile.html

{% extends "account.html" %}

{% block extra_head_content  %}
    <link rel="stylesheet" type="text/css" href="/static/css/edit_profile.css" />
{% endblock %}

{% block account_content %}
    Welcome to your profile
{% endblock %}

Upvotes: 30

Views: 22654

Answers (2)

James Fletcher
James Fletcher

Reputation: 920

The django-sekizai module takes care of addition to css and javascript with ease:

#base.html
{% load sekizai_tags %}
# define your template, declaring blocks for inheriting templates:
{% block content %}
{% endblock content %}
# at the bottom of the body:
{% render_block "js" %}
</body>
</html>

#my_template.html
{% extends "base.html" %}
{% load sekizai_tags %}
{% block content %}
# content goes here...
# so does the addtoblock tag
    {% addtoblock "js" %}
        <script src="my/awesome/script.js"></script>
    {% endaddtoblock %}
{% endblock content %}
# Note no addtoblock tags outside the block-endblock tags

The sekazai docs make clear the caveats for using this system, namely that:

  1. render_block should only be used outside block tags
  2. render_block cannot be used in included templates
  3. addtoblock should be used inside block tags when used in an included template

Upvotes: 3

Chris Pratt
Chris Pratt

Reputation: 239260

No, but you can use {{ block.super }}:

{% block extra_head_content  %}
    {{ block.super }}
    <link rel="stylesheet" type="text/css" href="/static/css/account.css" />
{% endblock %}

Upvotes: 55

Related Questions