views:

39

answers:

2

If you want to override a template coming with an app in django (in app/templates/app/) you create a template of the same name in another directory, which the template loader checks before the app's template dir. If you just want to override certain blocks of the template you also have to copy the whole template ad change that block, which is actually not very DRY.

Does anybody know a way to override the orginial template, while at the same moment extending it, so that you just have to override the specific block you want to change? (the thing is doing this without changing the template's name, because in some cases you might have to change the view to make it work with another template)

A: 

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.

Paulo Scardine
Thanks for posting this but my question is not about ADMIN templates. I'm seeking for doing something like this with (frontend)templates that eg. come with a third party app, where I probably just want to change a block, and copying the whole rest to override just a part looks like some DRY violation to me...
lazerscience
@lazerscience: it's the same process, except in your template directory you should adhere to the same directory structure as the templates that you are overriding. Check: http://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.loader.select_template
Andrew Sledge
I don't think this still answers the original question. Say that `niceapp.views.index()` uses the template `niceapp/index.html`. If I want to use the original view but customize the template, I can create a `niceapp/index.html` in a `templates` directory of my project or my own app. But how to extend the original and override just some blocks, and not copy the whole template? Saying `{% extend "niceapp/index.html" %}` apparently doesn't do the job.
akaihola
+1  A: 

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.

akaihola
Thanks, thats also not 100% what I was looking for, but I don't think you can get any closer; was already doing something similar when customizing templatesd for different sites!
lazerscience