[Fixed]-Overwriting a block within an `include`d template from an extended template

14đź‘Ť

âś…

from the docs

The include tag should be considered as an implementation of “render this subtemplate and include the HTML”, not as “parse this subtemplate and include its contents as if it were part of the parent”. This means that there is no shared state between included templates — each include is a completely independent rendering process.

so the subtemplate (header.html) is getting fully rendered and inserted into the parent template (base.html), meaning there is no concept of the block for the child template (homepage.html) to overwrite

6đź‘Ť

This is a known limitation that we hope be solved in a near future.

By the way, presuming that you have a more complex problem that you have mentioned, another work around for this is making header a block and than overriding this block with a new custom include.

base.html

<html>
    {% block header %}
        {% include 'header.html' %}
    {% endblock %}
    <div>
        {% block content %}Default Content{% endblock %}
    </div>
</html>

header.html

<header>
     {% block logo %}Logo 1{% endblock %}
</header>

homepage.html

{% extends 'base.html' %}

{% block header %}
    {% include 'homepage_header.html' %}
{% endblock %}

{% block content %}Yap Yap Yap{% endblock %}

homepage_header.html

{% extends 'header.html' %}

{% block logo %}Logo 2{% endblock %}
👤caio

2đź‘Ť

I had a similar problem. I have a filtered table template which is of form

{% extends 'base.html' %}
{% include 'filtered_table.html' %}

where filtered_table.html is:

{% load render_table from django_tables2 %}
<div class="panel-body" >
  <form method='GET'>
  <div class="search-form" style="border: 1px solid #000000; background-color:#a3ffaf; overflow: auto;">
{% block render_form %}
    {% for field in filter.form %}
         {{ field.errors }}
         {{ field.label_tag }} {{ field }}
    {% endfor %}
{% endblock %}
    <input type='submit' value='Filter' />
    |
    Displaying {{ filter.qs.count }} of {{ filter.queryset.count }} {{ object_name }}s.
    |
    <a href='{{ request.path }}' >Clear</a> <p>
  </div>

{% if table %}
    {% render_table table %}
{% endif %}

</form>

</div>

I may want to specially hand-craft the form, for example by spelling out each field like this:

{% block render_form %}
{{ filter.form.field1.errors }}
{{ filter.form.field1.label_tag }}
{{ filter.form.field1 }}
<p>

{{ filter.form.field2.errors }}
{{ filter.form.field2.label_tag }}
{{ filter.form.field2 }} 
{% endblock %}

Unfortunately, because I can’t do “extends” twice, I can’t get my base layout and customize the filtered table. So the ugly (because breaks HTML structure in half) way to do this is to simply define begin_filtered_table.html and end_filtered_table.html. Then in the customized case I have two includes wrapping the customization, and for the uncustomized case, filtered_form.html is defined like this:

{% include "begin_filtered_table.html" %}

    {% for field in filter.form %}
         {{ field.errors }}
         {{ field.label_tag }} {{ field }}
    {% endfor %}

{% include "end_filtered_table.html" %}

This solves the problem at the expense of being gross. It would be much easier just to allow multiple extends.

👤Lars Ericson

1đź‘Ť

You cannot overwrite the logo from homepage.html because it’s not defined in the base template itself.

The solution is, as you propose, to move the header.html code into base.html

👤Wesley

Leave a comment