The MAIN thing about Django templates

For about a year now, I’ve been harping about using {% block main %}, and today, I got affirmation that it is the right thing to do. I saw an article posted about it in A List Apart’s feed and started investigating.

So it’s looking likely that we’ll have a <main> tag soon. I’ll skip over the specifics because you’re probably already using <div class="main">. It is one of the most common elements and even more so now that .nav, .header, and .footer are now <nav> <header>, and <footer>.

The important thing to remember is there can only be one <main> tag on a page. And it just so happens that you can only have one {% block main %} in a Django template (barring some trickery). So how to use it? The obvious way is something like:

{% extends "site_base.html" %}
{% comment %} Don't actually use main like this {% endcomment %}
{% block main %}
  <main>
    {# Your content #}
  </main>
{% endblock %}

But not so fast! Django templates can divided into three categories: base/layout templates, detail/leaf templates, and includes/shared/component templates (which I’ll ignore for the rest of this post). So here’s how your templates should look like. The base, layouts/base.html:

{% extends "site_base.html" %}
{% block body %}
  {% block main_container %}
    <main role="main">
      {% block main %}{% endblock %}
    </main>
  {% endblock %}
{% endblock %}

And the leaf:

{% extends "layouts/base.html" %}
{% block main %}
  {{ object }}      
{% endblock %}

So why have a block immediately surrounding the <main>? Well you’re going to find it hard to make variations of base templates without it. To extend an existing base, load the structure into {% main_container %} and re-provide {% block main %} like this:

{% extends "layouts/base.html" %}
{% block body %}
  {% block main_container %}
    <div class="row">
      <div class="span8">
        <main role="main">
          {% block main %}{% endblock %}
        </main>
      </div>
      <div class="span4">
        <aside>
          {% block rail %}{% endblock %}
        </aside>
      </div>
    </div>
  {% endblock %}
{% endblock %}

Now you’re guaranteed to have your main content rendered no matter which base you extend because every base template provides a main block.

And finally, don’t actually use <main> since it’s only a draft spec. Use <div class="main" role="main"> instead.

Leave a Reply

Your email address will not be published. Required fields are marked *