如何覆盖和扩展基本的 Django 管理模板?
- 2024-12-27 08:47:00
- admin 原创
- 110
问题描述:
如何覆盖管理模板(例如 admin/index.html)同时扩展它(请参阅https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacing-an-admin-template)?
首先 - 我知道这个问题之前已经被问过并回答过(请参阅Django:覆盖和扩展应用程序模板),但正如答案所说,如果你使用app_directories模板加载器(大多数情况下),它并不直接适用。
我目前的解决方法是复制并从中扩展,而不是直接从管理模板中扩展。这种方法效果很好,但确实很混乱,而且当管理模板更改时会增加额外的工作。
它可以考虑为模板提供一些自定义的扩展标签,但如果已经存在解决方案,我就不想重新发明轮子。
附注:有人知道 Django 本身是否会解决这个问题吗?
解决方案 1:
更新:
阅读你所用Django版本的文档,例如最新版本或旧LTS版本 :3.2、2.2、1.11
2011 年的原始答案:
大约一年半前,我遇到过同样的问题,后来我在 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 %}
我已经在我的网站的博客文章中给出了如何使用此模板加载器的完整示例。
解决方案 2:
由于 Django 1.8 是当前版本,因此无需符号链接、将 admin/templates 复制到项目文件夹或安装中间件(如上述答案所建议)。以下是操作方法:
创建以下树结构(官方文档推荐)
your_project
|-- your_project/
|-- myapp/
|-- templates/
|-- admin/
|-- myapp/
|-- change_form.html <- do not misspell this
注意:此文件的位置并不重要。您可以将其放在应用程序内部,它仍会工作。只要 django 可以发现其位置即可。更重要的是,HTML 文件的名称必须与 django 提供的原始 HTML 文件名相同。
将此模板路径添加到您的settings.py:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # <- add this line
'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 modification here #}
{% endblock %}
加载你的页面,你应该会看到变化
解决方案 3:
如果需要覆盖admin/index.html
,可以设置的index_templateAdminSite
参数。
例如
# 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
解决方案 4:
在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
一个简单的 html 模板扩展admin/change_form.html
(或者如果你想从头开始做的话)
解决方案 5:
我在官方 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):
# set values for `site_header`, `site_title`, `index_title` etc.
site_header = 'Custom Admin Site'
...
# extend / override admin views, such as `index()`
def index(self, request, extra_context=None):
extra_context = extra_context or {}
# do whatever you want to do and save the values in `extra_context`
extra_context['world'] = 'Earth'
return super(CustomAdminSite, self).index(request, extra_context)
custom_admin_site = CustomAdminSite()
确保在您的应用程序custom_admin_site
中导入admin.py
并在其中注册您的模型,以便在您的自定义管理网站上显示它们(如果您愿意)。
在 中
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
,将 替换django.admin.site
为INSTALLED_APPS
(apps.CustomAdminConfig
上一步中的自定义管理应用程序配置)。在
mysite/urls.py
,将admin.site.urls
管理员 URL 替换为custom_admin_site.urls
from .admin import custom_admin_site
urlpatterns = [
...
path('admin/', custom_admin_site.urls),
# for Django 1.x versions: url(r'^admin/', include(custom_admin_site.urls)),
...
]
在目录中创建要修改的模板,并维护文档
templates
中指定的默认 Django 管理模板目录结构。例如,如果您要修改,请创建文件。admin/index.html
`templates/admin/index.html`
所有现有的模板都可以通过这种方式修改,它们的名称和结构可以在Django的源代码中找到。
现在,您可以通过从头开始编写来覆盖模板,或者扩展它,然后覆盖/扩展特定的块。
例如,如果您希望保持一切原样,但又想覆盖该content
块(该块在索引页上列出了您注册的应用程序及其模型),请将以下内容添加到templates/admin/index.html
:
{% extends 'admin/index.html' %}
{% block content %}
<h1>
Hello, {{ world }}!
</h1>
{% endblock %}
要保留块的原始内容,{{ block.super }}
请在希望显示原始内容的任何位置添加:
{% extends 'admin/index.html' %}
{% block content %}
<h1>
Hello, {{ world }}!
</h1>
{{ block.super }}
{% endblock %}
您还可以通过修改extrastyle
和extrahead
块来添加自定义样式和脚本。
解决方案 6:
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
对于无法通过这种方式覆盖的模板,您仍然可以为整个项目覆盖它们。只需将新版本放在templates/admin目录中即可。这对于创建自定义 404 和 500 页面特别有用
我必须覆盖管理员的 login.html,因此必须将覆盖的模板放在这个文件夹结构中:
your_project
|-- your_project/
|-- myapp/
|-- templates/
|-- admin/
|-- login.html <- do not misspell this
(没有管理员中的 myapp 子文件夹)我没有足够的声誉来评论 Cheng 的帖子,这就是我不得不将其写为新答案的原因。
解决方案 7:
最好的方法是将 Django 管理模板放入您的项目中。这样您的模板就会在,templates/admin
而普通的 Django 管理模板则会在template/django_admin
。然后,您可以执行以下操作:
模板/管理员/change_form.html
{% extends 'django_admin/change_form.html' %}
Your stuff here
如果您担心保持库存模板保持最新,您可以将它们包含在 svn externals 或类似程序中。
解决方案 8:
对于应用程序索引,请将这一行添加到某个常见的 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"
等,并在同一个管理员的模块类中找到其他
解决方案 9:
您可以通过多种方式覆盖 django 管理模板。
例如django-project
如下图所示:
django-project
|-core
| └-settings.py
|-app1
| |-models.py
| └-admin.py
|-app2
└-templates
然后,BASE_DIR / 'templates'
设置为DIRS
,TEMPLATES
以便settings.py
文件templates
夹被识别,如下所示:
# "core/settings.py"
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
BASE_DIR / 'templates', # Here
],
'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',
],
},
},
]
并且,有Food
和Drink
型号如下app1/models.py
图所示:
# "app1/models.py"
class Food(models.Model):
name = models.CharField(max_length=20)
class Drink(models.Model):
name = models.CharField(max_length=20)
并且,有Food
和Drink
管理员,app1/admin.py
如下所示:
# "app1/admin.py"
@admin.register(Food)
class FoodAdmin(admin.ModelAdmin):
pass
@admin.register(Drink)
class DrinkAdmin(admin.ModelAdmin):
pass
现在,您可以覆盖、和中的其中一个 django 管理模板change_form.html ,如下所示。 *您可以从虚拟环境中复制django管理模板,并且某些 django 管理模板无法在或中被覆盖,但这些 django 管理模板可以在、和中全部覆盖,您可以看到我的回答,其中解释了哪些 django 管理模板可以在哪些目录中被覆盖。templates/admin/
`templates/admin/app1/templates/admin/app1/food/
django/contrib/admin/templates/admin/templates/admin/app1/
templates/admin/app1/food/templates/admin/
templates/admin/app1/`templates/admin/app1/food/
change_form.html
下面的templates/admin/
可以自动应用于所有应用程序中的所有管理员。 *小写的文件夹名称admin
可以正常工作:
django-project
|-core
| └-settings.py
|-app1
| |-models.py
| └-admin.py
|-app2
└-templates
└-admin
└-change_form.html # Here
change_form.html
下面的templates/admin/app1/
可以自动应用于 中的所有管理员app1
。 *小写的文件夹名称app1
可以正常工作:
django-project
|-core
| └-settings.py
|-app1
| |-models.py
| └-admin.py
|-app2
└-templates
└-admin
|-app1
| └-change_form.html # Here
└-app2
change_form.html
下面的templates/admin/app1/food/
可以自动应用到food
中的管理员app1
。 *小写的文件夹名称food
可以正常工作:
django-project
|-core
| └-settings.py
|-app1
| |-models.py
| └-admin.py
|-app2
└-templates
└-admin
|-app1
| |-food
| | └-change_form.html # Here
| └-drink
└-app2
现在,您可以重命名,但任何文件夹中的重命名change_form.html
都custom_change_form.html
无法custom_change_form.html
自动应用于任何应用程序中的任何管理员。因此,您需要手动应用于custom_change_form.html
您想要应用custom_change_form.html
的任何应用程序中的任何管理员。
custom_change_form.html
如下所示templates/admin/
:
django-project
|-core
| └-settings.py
|-app1
| |-models.py
| └-admin.py
|-app2
└-templates
└-admin
└-custom_change_form.html # Here
设置admin/custom_change_form.html
为change_form_template和admins 如下所示。 *您可以找到更多自Food
定义模板选项:Drink
# "app1/admin.py"
@admin.register(Food)
class FoodAdmin(admin.ModelAdmin):
change_form_template = 'admin/custom_change_form.html'
@admin.register(Drink)
class DrinkAdmin(admin.ModelAdmin):
change_form_template = 'admin/custom_change_form.html'
custom_change_form.html
如下所示templates/admin/app1/
:
django-project
|-core
| └-settings.py
|-app1
| |-models.py
| └-admin.py
|-app2
└-templates
└-admin
|-app1
| └-custom_change_form.html # Here
└-app2
设置admin/app1/custom_change_form.html
为change_form_template
inFood
和Drink
admins如下图所示:
# "app1/admin.py"
@admin.register(Food)
class FoodAdmin(admin.ModelAdmin):
change_form_template = 'admin/app1/custom_change_form.html'
@admin.register(Drink)
class DrinkAdmin(admin.ModelAdmin):
change_form_template = 'admin/app1/custom_change_form.html'
custom_change_form.html
如下所示templates/admin/app1/food
:
django-project
|-core
| └-settings.py
|-app1
| |-models.py
| └-admin.py
|-app2
└-templates
└-admin
|-app1
| |-food
| | └-custom_change_form.html # Here
| └-drink
└-app2
设置admin/app1/food/custom_change_form.html
为change_form_template
inFood
和Drink
admins如下图所示:
# "app1/admin.py"
@admin.register(Food)
class FoodAdmin(admin.ModelAdmin):
change_form_template = 'admin/app1/food/custom_change_form.html'
@admin.register(Drink)
class DrinkAdmin(admin.ModelAdmin):
change_form_template = 'admin/app1/food/custom_change_form.html'
解决方案 10:
我同意 Chris Pratt 的观点。但我认为最好创建指向管理模板所在的原始 Django 文件夹的符号链接:
ln -s /usr/local/lib/python2.7/dist-packages/django/contrib/admin/templates/admin/ templates/django_admin
如您所见,它取决于 Python 版本和 Django 安装的文件夹。因此,将来或在生产服务器上,您可能需要更改路径。
解决方案 11:
该站点有一个简单的解决方案,适用于我的 Django 1.7 配置。
首先:在项目的 template/ 目录中创建一个名为admin_src的符号链接,指向已安装的 Django 模板。对于我在 Dreamhost 上使用虚拟环境的我来说,我的“源”Django 管理模板位于:
~/virtualenvs/mydomain/lib/python2.7/site-packages/django/contrib/admin/templates/admin
第二:在 templates/ 中创建一个管理目录
所以我的项目的模板/目录现在看起来像这样:
/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 文件夹中。
完成。简单。
解决方案 12:
您可以使用django-overextends,它为 Django 提供循环模板继承。
它来自Mezzanine CMS,Stephen 将其提取到独立的 Django 扩展中。
您可以在 Mezzanine 文档中的“覆盖与扩展模板”(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):”后面省略了一个斜线。也许声誉更好的人可以修复链接并删除此注释。