如何覆盖和扩展基本的Django管理模板?

Sem*_*mel 113 python django django-admin

如何覆盖管理模板(例如admin/index.html),同时扩展它(请参阅https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacing -an-admin-template)?

首先 - 我知道之前已经提出并回答了这个问题(参见Django:覆盖和扩展应用程序模板),但正如答案所说,如果您使用的是app_directories模板加载器(大部分是时间).

我目前的解决方法是从它们进行复制和扩展,而不是直接从管理模板扩展.这非常有效,但是当管理模板发生变化时,它会让人感到困惑并增加额外的工作量.

它可以考虑模板的一些自定义扩展标记,但如果已经存在解决方案,我不想重新发明轮子.

旁注:有人知道Django本身是否会解决这个问题?

hey*_*man 97

更新:

阅读您的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

2011年的原始答案:

大约一年半前我遇到了同样的问题,我在djangosnippets.org上发现了一个很好的模板加载器,这使得这很简单.它允许您在特定应用程序中扩展模板,使您能够创建自己的admin/index.html,从admin应用程序扩展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 %}
Run Code Online (Sandbox Code Playgroud)

我已经在我的网站上的博客文章中给出了如何使用此模板加载器的完整示例.

  • 以供参考; 有问题的片段已转换为django应用程序,并在PyPi(pip/easy_install)中以django-apptemplates的形式提供:http://pypi.python.org/pypi/django-apptemplates/ (17认同)
  • 只是100%明确:上面的解决方案将不再适用于最近版本的Django(至少1.4),因为脚本使用的其中一个函数是折旧的.[你可以在这里找到更新的来源](https://bitbucket.org/wojas/django-apptemplates) (9认同)
  • 请注意,对于Django 1.8,这仍然有效,但需要以特殊方式进行设置(请参阅[app_namespace.Loader setup](https://github.com/Fantomas42/django-app-namespace-template-loader#安装)作为例子).[django-app-namespace-template-loader](https://pypi.python.org/pypi/django-app-namespace-template-loader)也可以替代`django-apptemplates`,如果它可能停止工作一天. (2认同)

Che*_*eng 67

至于Django 1.8是当前版本,不需要符号链接,将admin/templates复制到项目文件夹,或者按照上面的答案建议安装中间件.这是做什么的:

  1. 创建以下树结构(官方文档推荐)

    your_project
         |-- your_project/
         |-- myapp/
         |-- templates/
              |-- admin/
                  |-- myapp/
                      |-- change_form.html  <- do not misspell this
    
    Run Code Online (Sandbox Code Playgroud)

注意:此文件的位置并不重要.你可以把它放在你的应用程序中,它仍然可以工作.只要它的位置可以被django发现.更重要的是HTML文件的名称必须与django提供的原始HTML文件名相同.

  1. 将此模板路径添加到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',
                ],
            },
        },
    ]
    
    Run Code Online (Sandbox Code Playgroud)
  2. 标识要覆盖的名称和块.这是通过查看django的admin/templates目录来完成的.我正在使用virtualenv,所以对我来说,路径在这里:

    ~/.virtualenvs/edge/lib/python2.7/site-packages/django/contrib/admin/templates/admin
    
    Run Code Online (Sandbox Code Playgroud)

在此示例中,我想修改添加新用户表单.此视图的模板责任是change_form.html.打开change_form.html并找到要扩展的{%block%}.

  1. 你的change_form.html中,写下这样的东西:

    {% extends "admin/change_form.html" %}
    {% block field_sets %}
         {# your modification here #}
    {% endblock %}
    
    Run Code Online (Sandbox Code Playgroud)
  2. 加载页面,您应该看到更改


gin*_*ime 47

如果需要覆盖admin/index.html,可以设置index_template参数AdminSite.

例如

# urls.py
...
from django.contrib import admin

admin.site.index_template = 'admin/my_custom_index.html'
admin.autodiscover()
Run Code Online (Sandbox Code Playgroud)

并将您的模板放入 <appname>/templates/admin/my_custom_index.html

  • 辉煌!这样做可以让你从my_custom_index.html执行`{%extends"admin/index.html"%}`并在没有复制它的情况下引用django管理模板.谢谢. (4认同)
  • @Semmel应该将此标记为正确答案,因为它是使用内置django功能的最简单方法,并且不需要使用自定义模板加载器. (3认同)

maa*_*zza 17

使用django1.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'
Run Code Online (Sandbox Code Playgroud)

随着change_form.html一个简单的html模板扩展admin/change_form.html(或者如果你想从头开始)


mat*_*yas 7

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
Run Code Online (Sandbox Code Playgroud)

对于那些无法以这种方式覆盖的模板,您仍然可以为整个项目覆盖它们.只需新版本放在模板/管理目录中即可.这对于创建自定义404和500页特别有用

我不得不覆盖管理员的login.html,因此必须将覆盖的模板放在这个文件夹结构中:

your_project
 |-- your_project/
 |-- myapp/
 |-- templates/
      |-- admin/
          |-- login.html  <- do not misspell this
Run Code Online (Sandbox Code Playgroud)

(没有管理员中的myapp子文件夹)我没有足够的评论来评论Cheng的帖子这就是为什么我不得不写这个作为新的答案.


Fah*_*mad 7

我在官方 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/
Run Code Online (Sandbox Code Playgroud)

您需要执行以下操作:

  1. 在 中mysite/admin.py,创建一个子类AdminSite

    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/
    
    Run Code Online (Sandbox Code Playgroud)

    确保导入custom_admin_siteadmin.py你的应用程序并注册它的模型在您的自定义管理网站显示它们(如果你愿意的话)。

  2. 在 中mysite/apps.py,创建一个子类AdminConfig并从上一步设置default_siteadmin.CustomAdminSite

    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()
    
    Run Code Online (Sandbox Code Playgroud)
  3. mysite/settings.py,替换django.admin.siteINSTALLED_APPSapps.CustomAdminConfig(来自之前的步骤自定义管理应用程序配置)。

  4. 在 中mysite/urls.pyadmin.site.urls从管理 URL替换为custom_admin_site.urls

    from django.contrib.admin.apps import AdminConfig
    
    
    class CustomAdminConfig(AdminConfig):
        default_site = 'admin.CustomAdminSite'
    
    Run Code Online (Sandbox Code Playgroud)
  5. templates目录中创建要修改的模板,维护docs 中指定的默认 Django 管理模板目录结构。例如,如果您正在修改admin/index.html,则创建文件templates/admin/index.html.

    所有现有的模板都可以通过这种方式进行修改,它们的名称和结构可以在Django 的源代码中找到

  6. 现在,您可以通过从头开始编写模板来覆盖模板,也可以扩展它然后覆盖/扩展特定块。

    例如,如果您想保留所有内容但想覆盖content块(在索引页面上列出了您注册的应用程序及其模型),请将以下内容添加到templates/admin/index.html

    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)),
        ...
    ]
    
    Run Code Online (Sandbox Code Playgroud)

    要保留块{{ block.super }}的原始内容,请在要显示原始内容的任何位置添加:

    {% extends 'admin/index.html' %}
    
    {% block content %}
      <h1>
        Hello, {{ world }}!
      </h1>
    {% endblock %}
    
    Run Code Online (Sandbox Code Playgroud)

    您还可以通过修改extrastyleextrahead块来添加自定义样式和脚本。


Chr*_*att 5

最好的方法是将Django管理模板放在项目中.因此,您的模板将在templates/adminDjango管理模板库存中template/django_admin.然后,您可以执行以下操作:

模板/管理/ change_form.html

{% extends 'django_admin/change_form.html' %}

Your stuff here
Run Code Online (Sandbox Code Playgroud)

如果您担心保持库存模板的最新状态,可以使用svn externals或类似物品包含它们.