Please read this in full - you will not be disappointed by the end.
We often talk about "multiple-inheritance" when referring to multiple
levels of {% extends ... %} and defining {% block ... %} many layers up in
base templates.
But, something that comes up as a useful idea in my mind on a regular basis
when working in Django templates is the ability to actually inherit from
multiple base templates.
The immediate reaction to this idea might be repulsion until you think
through the implications and weigh them against the benefits.
An example (simplified) use case speaks louder than explanation:
*base.html*
<a>Some top-level menu</a>
{% block submenu %}{% endblock %}
{% block content %}{% endblock %}
--
*orders/base.html*
{% extends 'base.html' %}
{% block submenu %}
<a>View all Orders</a>
<a>Enter an Order</a>
{% endblock %}
--
*products/base.html*
{% extends 'base.html' %}
{% block submenu %}
<a>View all Products</a>
<a>Create a Product</a>
{% endblock %}
--
So, we have a relatively common template setup, with some apps defining
their own base templates that extend the main base template, and then
defining their own submenus, etc.
At this point, we know there will be a product list page and an order list
page, but we also know that the product list template will extend the
product base template and the order list template will extend the order
base template; same goes for the product create and order create, both also
extending their respective apps' base templates.
This means duplication. The product list template will contain most of the
same list-related HTML, etc. as the order list, but the only way to avoid
that duplication will be to make a base list template and extend that
template from both the product list and order list.
*generic-list.html*
{% extends 'base.html' %}
{% block content %}
<ul>
{% for object in page.object_list %}
{% block list-item %}
<li>{{ object }}</li>
{% endblock %}
{% endfor %}
</ul>
{% endblock %}
--
But, in this case we lose the benefit of the product base and order base
(the submenus they define). Submenus are a super simplified example, but in
reality there may be *many* different things about a given app's base
template, making it a dilemma, or simply removing the practical ability to
subclass a "generic list" template altogether.
*Introducing multiple-inheritance:*
*orders/list.html*
{% extends 'generic-list.html 'orders/base.html' %}
{% block list-item %}
<li>Order # {{ order.id }} (total: {{ order.total }})</li>
{% endblock %}
--
*products/list.html*
{% extends 'generic-list.html 'products/base.html' %}
{% block list-item %}
<li>Product # {{ product.id }} (price: {{ product.price }})</li>
{% endblock %}
--
The order of the templates would define the order of block definition and
override precedence, from left to right (similar to Python class MRO).
You can also see, by the overriding of the "list-item" block, that there
are other benefits of using extension like this, compared to e.g., defining
a list template as an include, as a workaround.
Each template in the list would need to extend from template at the very
right, meaning that each template left of the main template would
essentially be a mixin. This would solve the very real problem of making
generic bases for types of templates (list, detail, form, etc.) in your
app, while still preserving the benefits of extension (block overrides) to
all other facets of your final templates (vs having to use includes).
--
You received this message because you are subscribed to the Google Groups
"Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-developers/cc068a12-04ee-481a-81e1-919ed958c688%40googlegroups.com.