如何在扩展管理模板(例如 admin/index.html)的同时对其进行扩展(参见 https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacing-an-admin-template)?
首先 - 我知道这个问题之前已经被问过并得到了回答(参见 Django: Overriding AND extending an app template),但正如答案所说,如果您使用 app_directories 模板加载器(大多数情况下),它并不直接适用。
我目前的解决方法是制作副本并从它们扩展,而不是直接从管理模板扩展。这很好用,但是当管理模板更改时,它确实令人困惑并且增加了额外的工作。
它可以为模板考虑一些自定义扩展标签,但如果已经存在解决方案,我不想重新发明轮子。
附带说明:有人知道这个问题是否会由 Django 本身解决吗?
更新:
阅读您的 Django 版本的文档。例如
https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#admin-overriding-templates https://docs.djangoproject.com/en/2.0/ref/contrib/admin/#admin-overriding-templates https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#admin-overriding-templates
2011年的原始答案:
大约一年半前我遇到了同样的问题,我发现了一个很好的 template loader on djangosnippets.org 可以让这很容易。它允许您在特定应用程序中扩展模板,使您能够创建自己的 admin/index.html 以从管理应用程序扩展 admin/index.html 模板。像这样:
{% extends "admin:admin/index.html" %}
{% block sidebar %}
{{block.super}}
<div>
<h1>Extra links</h1>
<a href="/admin/extra/">My extra link</a>
</div>
{% endblock %}
我已在我的网站上的 blog post 中提供了有关如何使用此模板加载器的完整示例。
至于当前版本的 Django 1.8,无需符号链接,将 admin/templates 复制到您的项目文件夹,或按照上述答案的建议安装中间件。这是做什么:
创建如下树结构(官方文档推荐) your_project |-- your_project/ |-- myapp/ |-- templates/ |-- admin/ |-- myapp/ |-- change_form.html <- 不要拼错
注意:此文件的位置并不重要。你可以把它放在你的应用程序中,它仍然可以工作。只要它的位置可以被django发现。更重要的是 HTML 文件的名称必须与 django 提供的原始 HTML 文件名相同。
将此模板路径添加到您的 settings.py: TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], # <- 添加这一行 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors. auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] 确定您要覆盖的名称和块。这是通过查看 django 的 admin/templates 目录来完成的。我正在使用 virtualenv,所以对我来说,路径在这里:~/.virtualenvs/edge/lib/python2.7/site-packages/django/contrib/admin/templates/admin
在这个例子中,我想修改添加新用户表单。这个视图的模板是 change_form.html。打开 change_form.html 并找到要扩展的 {% block %}。
在您的 change_form.html 中,编写如下内容: {% extends "admin/change_form.html" %} {% block field_sets %} {# your modify here #} {% endblock %} 加载您的页面,您应该会看到变化
../
写入“扩展”路径并指定更独特的原始路径 {% extends "../../admin/templates/admin/index.html" %}
。 link to answer
如果需要覆盖admin/index.html
,可以设置AdminSite
的index_template参数。
例如
# urls.py
...
from django.contrib import admin
admin.site.index_template = 'admin/my_custom_index.html'
admin.autodiscover()
并将您的模板放入 <appname>/templates/admin/my_custom_index.html
{% extends "admin/index.html" %}
并让其引用 django 管理模板而不复制它。谢谢你。
使用 django
1.5(至少)您可以定义要用于特定 modeladmin
的模板
见https://docs.djangoproject.com/en/1.5/ref/contrib/admin/#custom-template-options
你可以做类似的事情
class Myadmin(admin.ModelAdmin):
change_form_template = 'change_form.htm'
change_form.html
是一个扩展 admin/change_form.html
的简单 html 模板(如果您想从头开始,也可以不用)
Chengs 的回答是正确的,但是根据管理文档,并不是每个管理模板都可以这样覆盖:https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#overriding-admin-templates
每个应用程序或模型可以覆盖的模板 不是每个应用程序或模型都可以覆盖 contrib/admin/templates/admin 中的每个模板。以下可以: app_index.html change_form.html change_list.html delete_confirmation.html object_history.html 对于那些无法以这种方式覆盖的模板,您仍然可以在整个项目中覆盖它们。只需将新版本放在您的模板/管理目录中。这对于创建自定义 404 和 500 页面特别有用
我必须覆盖管理员的 login.html,因此必须将覆盖的模板放在此文件夹结构中:
your_project
|-- your_project/
|-- myapp/
|-- templates/
|-- admin/
|-- login.html <- do not misspell this
(在管理员中没有 myapp 子文件夹)我没有足够的声誉来评论 Cheng 的帖子,这就是为什么我不得不把它写成新的答案。
我在官方 Django 文档中找不到一个答案或一个部分,其中包含我需要覆盖/扩展默认管理模板的所有信息,所以我将这个答案写成一个完整的指南,希望它会有所帮助为将来的其他人。
假设标准的 Django 项目结构:
mysite-container/ # project container directory
manage.py
mysite/ # project package
__init__.py
admin.py
apps.py
settings.py
urls.py
wsgi.py
app1/
app2/
...
static/
templates/
这是您需要做的:
在 mysite/admin.py 中,创建 AdminSite 的子类: from django.contrib.admin import AdminSite class CustomAdminSite(AdminSite): # 为 `site_header`、`site_title`、`index_title` 等设置值 site_header = 'Custom Admin Site' ... # 扩展/覆盖管理视图,例如 `index()` def index(self, request, extra_context=None): extra_context = extra_context or {} # 做任何你想做的事情并将值保存在`extra_context` extra_context['world'] = 'Earth' return super(CustomAdminSite, self).index(request, extra_context) custom_admin_site = CustomAdminSite() 确保在您的应用程序的 admin.py 中导入 custom_admin_site 并注册您的模型它将它们显示在您的自定义管理站点上(如果您愿意)。在 mysite/apps.py 中,创建 AdminConfig 的子类,并将上一步中的 default_site 设置为 admin.CustomAdminSite: from django.contrib.admin.apps import AdminConfig class CustomAdminConfig(AdminConfig): default_site = 'admin.CustomAdminSite' 中mysite/settings.py,将 INSTALLED_APPS 中的 django.admin.site 替换为 apps.CustomAdminConfig(您在上一步中的自定义管理应用配置)。在 mysite/urls.py 中,将 admin.site.urls 从 admin URL 替换为 custom_admin_site.urls from .admin import custom_admin_site urlpatterns = [ ... path('admin/', custom_admin_site.urls), # for Django 1.x版本: url(r'^admin/', include(custom_admin_site.urls)), ... ] 在模板目录中创建要修改的模板,维护文档中指定的默认 Django 管理模板目录结构。例如,如果您正在修改 admin/index.html,请创建文件 templates/admin/index.html。所有现有的模板都可以通过这种方式进行修改,它们的名称和结构可以在 Django 的源代码中找到。现在,您可以通过从头开始编写模板来覆盖模板,也可以对其进行扩展,然后覆盖/扩展特定块。例如,如果您想保持一切原样但想覆盖内容块(在索引页面上列出了您注册的应用程序及其模型),请将以下内容添加到 templates/admin/index.html:{% extends 'admin/index.html' %} {% block content %}
最好的方法是将 Django 管理模板放入您的项目中。因此,您的模板将在 templates/admin
中,而库存 Django 管理模板将在 template/django_admin
中。然后,您可以执行以下操作:
模板/管理员/change_form.html
{% extends 'django_admin/change_form.html' %}
Your stuff here
如果您担心库存模板保持最新,您可以将它们包含在 svn externals 或类似内容中。
对于应用程序索引,将此行添加到某个常见的 py 文件中,例如 url.py
admin.site.index_template = 'admin/custom_index.html'
对于应用程序模块索引:将此行添加到 admin.py
admin.AdminSite.app_index_template = "servers/servers-home.html"
对于更改列表:将此行添加到管理类:
change_list_template = "servers/servers_changelist.html"
对于应用程序模块表单模板:将此行添加到您的管理类
change_form_template = "servers/server_changeform.html"
等并在同一个管理员的模块类中找到其他
我同意克里斯普拉特的观点。但我认为最好创建指向管理模板所在的原始 Django 文件夹的符号链接:
ln -s /usr/local/lib/python2.7/dist-packages/django/contrib/admin/templates/admin/ templates/django_admin
正如你所看到的,它取决于 python 版本和 Django 安装的文件夹。因此,将来或在生产服务器上,您可能需要更改路径。
This 网站有一个简单的解决方案,适用于我的 Django 1.7 配置。
首先:在项目的 template/ 目录中创建一个名为 admin_src 的符号链接,指向已安装的 Django 模板。对于在 Dreamhost 上使用 virtualenv 的我来说,我的“源”Django 管理模板位于:
~/virtualenvs/mydomain/lib/python2.7/site-packages/django/contrib/admin/templates/admin
第二:在templates/中创建一个admin目录
所以我的项目的 template/ 目录现在看起来像这样:
/templates/
admin
admin_src -> [to django source]
base.html
index.html
sitemap.xml
etc...
第三:在新的 template/admin/ 目录中创建一个包含以下内容的 base.html 文件:
{% extends "admin_src/base.html" %}
{% block extrahead %}
<link rel='shortcut icon' href='{{ STATIC_URL }}img/favicon-admin.ico' />
{% endblock %}
第四:将您的管理员 favicon-admin.ico 添加到您的静态根 img 文件夹中。
完毕。简单的。
您可以使用 django-overextends,它为 Django 提供循环模板继承。
它来自 Mezzanine CMS,Stephen 从那里将其提取到一个独立的 Django 扩展中。
您可以在夹层文档中的“覆盖与扩展模板”(http://mezzanine.jupo.org/docs/content-architecture.html#overriding-vs-extending-templates)中找到更多信息。
如需更深入的了解,请查看 Stephens 博客“Django 的循环模板继承”(http://blog.jupo.org/2012/05/17/circular-template-inheritance-for-django)。
在 Google Groups 中的讨论 (https://groups.google.com/forum/#!topic/mezzanine-users/sUydcf_IZkQ) 开始了此功能的开发。
笔记:
我没有添加超过 2 个链接的声誉。但我认为这些链接提供了有趣的背景信息。所以我只是在“http(s):”之后省略了一个斜杠。也许信誉更好的人可以修复链接并删除此注释。
不定期副业成功案例分享
django-apptemplates
的有效替代方案,如果它可能有一天会停止工作。