Django:覆盖并扩展应用程序模板

时间:2010-10-19 11:25:07

标签: django django-templates

如果要覆盖django中的应用程序附带的模板(在app / templates / app /中),则在另一个目录中创建一个同名模板,模板加载器在应用程序的模板目录之前检查该模板。如果您只想覆盖模板的某些块,您还必须复制整个模板广告更改该块,实际上这不是很干。

是否有人知道覆盖orginial模板的方法,同时在扩展它时,您只需要覆盖要更改的特定块? (事情是这样做没有更改模板的名称,因为在某些情况下,您可能需要更改视图以使其与另一个模板一起使用)

编辑:正如亚当泰勒在Django 1.9 on的评论中指出的那样,没有任何黑客攻击是可能的。

6 个答案:

答案 0 :(得分:35)

我认为this related question的答案是恰当的;目前,最好的解决方案似乎是使用django-apptemplates package on PyPI中的自定义模板加载器,因此您只需使用pip进行安装即可(例如pip install django-apptemplates)。

模板加载器允许您在特定应用中扩展模板;例如,要扩展管理界面的索引页面,您可以添加

'apptemplates.Loader',

TEMPLATE_LOADERS中的settings.py列表,然后使用

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

在你的模板中。

答案 1 :(得分:7)

作为更新,因为这似乎是一个受欢迎的问题。我没有任何问题地使用了overextends app。它提供了一个新的关键字过度扩展,允许扩展名称相同的模板。

使用pip很容易安装:

 pip install -U django-overextends

答案 2 :(得分:4)

Django 1.9及更高版本有this feature

  

Django模板加载器现在可以递归扩展模板。

所以你可以从app1获得一个包含以下内容的文件:

app1/templates/example/foobar.html

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

您可以使用app2中的文件对其进行扩展(请注意模板名称example/foobar.html是相同的):

app2/templates/example/foobar.html

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

最终结果应为:

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

答案 3 :(得分:2)

在Django wiki中,Simon Willison提出a trick来实现“自我扩展模板”效果。但是,如果您正在使用app_directories模板加载器,则不能直接应用。

在新目录中对应用程序的模板目录进行协同处理可能会有所帮助。

答案 4 :(得分:-1)

[更新]

我误解了这个问题,我的原始答案仅适用于具有内置模板扩展机制的管理员应用。对于缺乏这种机制的其他应用程序,我只是分叉原始模板而不是摆弄自定义模板加载器,如选择的答案建议。如果您担心分叉,您还可以实施扩展机制,如果您认为值得,可以回馈原始项目。


[原始答案]

直接从罚款manual: 由于管理模板的模块化设计,通常既不必要也不建议更换整个模板。最好只覆盖您需要更改的模板部分。

要继续上面的示例,我们要在“页面”模型的“历史记录”工具旁边添加新链接。在查看change_form.html之后,我们确定我们只需要覆盖对象工具块。因此,这是我们新的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 %}

就是这样!如果我们将此文件放在templates / admin / my_app目录中,我们的链接将出现在每个模型的更改表单中。

答案 5 :(得分:-3)

这样做的一个简单方法是:

假设你要扩展和覆盖django / contrib / admin / templates / admin / change_form.html。

首先,将原始的change_form.html复制到您应用的模板目录,并将其重命名为myapp / templates / admin / original_change_form.html。 (您也可以将其作为符号链接。)

其次,在myapp / templates / admin中创建自己的change_form.html。在它的顶部,添加以下内容:

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

简单!