[Django]-Django: Overriding AND extending an app template

37👍

I think the answer from this related question is pertinent; currently, the best solution seems to be to use a custom template loader from the django-apptemplates package on PyPI, so you can just use pip to install it (e.g. pip install django-apptemplates).

The template loader allows you to extend a template in a specific app; for example, to extend the index page of the admin inteface, you would add

'apptemplates.Loader',

to your TEMPLATE_LOADERS list in settings.py, and use

{% extends "admin:admin/index.html" %}

in your templates.

👤leech

10👍

Django 1.9 and later has this feature:

Django template loaders can now extend templates recursively.

So you can have a file from app1 with contents like this:

app1/templates/example/foobar.html:

<p>I'm from app1</p>
{% block main %}{% endblock %}

And you can extend it with a file from app2 (notice that the template name example/foobar.html is the same):

app2/templates/example/foobar.html:

{% extends "example/foobar.html" %}
{% block main %}
  <p>I'm from app2</p>
{% endblock %}

The end-result should be:

<p>I'm from app1</p>
<p>I'm from app2</p>
👤Flimm

7👍

As an update since this seems to be a popular question. I have used the overextends app without any problem. It provides a new keywords overextends that allows to extend templates with the same name.

And it is easy to install with pip:

 pip install -U django-overextends

2👍

In the Django wiki, Simon Willison presents a trick to achieve the “self-extending template” effect. It isn’t directly applicable if you’re using the app_directories template loader, though.

Symlinking apps’ templates directories inside a new directory might do a trick.

-1👍

[update]

I’ve misread the question, my original answer applies only to the admin app, which has a built-in template extension mechanism. For other app that lacks such mechanism, I would just fork the original templates instead of fiddling with custom template loaders like the chosen answer advises. If you are worried about forking, you can also implement an extension mechanism and contribute back to the original project if you think it is worth.


[original answer]

Straight from the fine manual:
Because of the modular design of the admin templates, it is usually neither necessary nor advisable to replace an entire template. It is almost always better to override only the section of the template which you need to change.

To continue the example above, we want to add a new link next to the History tool for the Page model. After looking at change_form.html we determine that we only need to override the object-tools block. Therefore here is our new change_form.html :

{% extends "admin/change_form.html" %}
{% load i18n %}
{% block object-tools %}
{% if change %}{% if not is_popup %}
  <ul class="object-tools">
    <li><a href="history/" class="historylink">{% trans "History" %}</a></li>
    <li><a href="mylink/" class="historylink">My Link</a></li>
    {% if has_absolute_url %}
        <li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">
            {% trans "View on site" %}</a>
        </li>
    {% endif%}
  </ul>
{% endif %}{% endif %}
{% endblock %}

And that’s it! If we placed this file in the templates/admin/my_app directory, our link would appear on every model’s change form.

-3👍

One simple way to do it is this:

Let’s say you want to extend and override django/contrib/admin/templates/admin/change_form.html.

First, copy the original change_form.html to your app’s template directory and rename it as something like myapp/templates/admin/original_change_form.html. (You could also do this as a symlink.)

Second, create your own change_form.html in myapp/templates/admin. At the top of it, put the following:

{% extends "admin/original_change_form.html" %}

Simple!

Leave a comment