Nest {% block %} in {% for %} Django template inheritance

307 Views Asked by At

I am developing a dictionary application using Django. One of the main themes of the app is displaying feeds of definitions.

Specifically, I have:

  1. an "index" feed where new definitions are listed,
  2. a "headword" feed where definitions of a particular headword are listed,
  3. and a "tag" feed where definitions tagged with a particular tag are listed.

index.html:

{% block body %}
    <h1>Definitions</h1>
    <ul>
        {% for definition in definitions %}
            // definition HTML
        {% endfor %}
    </ul>
{% endblock %}

headword.html:

{% block body %}
    <h1>{{ headword }}</h1>
    <ul>
        {% for definition in headword.definitions_headword.all %}
            // definition HTML
        {% endfor %}
    </ul>

tag.html:

{% block body %}
    <h1>{{ tag }}</h1>
    <ul>
        {% for definition in tag.definitions_tag.all %}
            // definition HTML
        {% endfor %}
    </ul>

Clearly, I need a base feed.html template that these three files can share. For the h1 tag no problem. However, I am having problems with the for loop iterable variables.

I tried nesting a {% block iterable %}{% endblock %} in the for loop of feed.html as in {% for definition in {% block iterable %}{% endblock %} %} and then plugging definitions, headword.definitions_headword.all, and tag.definitions_tag.all in {% block iterable %}, but Django does not seem to support that.

I could probably pass to all three templates a "definitions" context variable and use that as the iterable in all three for loops, but is there a way to do it without touching Python code?

1

There are 1 best solutions below

3
On BEST ANSWER

Your explanation was a bit fuzzy to me at the end there, but going just based off your first sentence of "Clearly, I need a base feed.html template that these three files can share."

I think {% include %} may be what you are looking for.

https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#include

  1. Create your base template of "feed.html" which includes generic variables. Generic variables below are "header_name" and "definitions".
<h1>{{ header_name }}</h1>
<ul>
    {% for definition in definitions %}
        // definition HTML
    {% endfor %}
</ul>
  1. In your parent templates (index, headword, tag), use the "include" tag. Pass in your parent template variables into the child template. Examples below:

headword.html

{% block body %}
    {% include 'pathname/feed.html' with header_name=headword definitions=headword.definitions_headword.all %}
{% endblock %}

tag.html

{% block body %}
    {% include 'pathname/feed.html' with header_name=tag definitions=tag.definitions_tag.all %}
{% endblock %}