【问题标题】:How to override and extend basic Django admin templates?如何覆盖和扩展基本的 Django 管理模板?
【发布时间】:2011-09-28 20:36:21
【问题描述】:

如何在扩展管理模板(例如 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 的当前状态,这不是最佳的工作流程。在三年的工作中,我还没有看到任何其他方法可以做你想做的事情:)
  • 嗯 - 我不知道这是否是一件好事,但至少像你这样的人得出了同样的结论。听起来还不错。 :)

标签: python django django-admin


【解决方案1】:

更新

阅读您的 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 中提供了一个完整的示例,说明如何使用此模板加载器。

【讨论】:

【解决方案2】:

对于当前版本的 Django 1.8,无需符号链接、将 admin/templates 复制到您的项目文件夹,或按照上述答案的建议安装中间件。这是做什么:

  1. 创建如下树结构(official documentation推荐)

    your_project
         |-- your_project/
         |-- myapp/
         |-- templates/
              |-- admin/
                  |-- myapp/
                      |-- change_form.html  <- do not misspell this
    

注意:此文件的位置并不重要。你可以把它放在你的应用程序中,它仍然可以工作。只要它的位置可以被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',
                ],
            },
        },
    ]
    
  2. 确定您要覆盖的名称和块。这是通过查看 django 的 admin/templates 目录来完成的。我正在使用 virtualenv,所以对我来说,路径在这里:

    ~/.virtualenvs/edge/lib/python2.7/site-packages/django/contrib/admin/templates/admin
    

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

  1. 您的 change_form.html 中,编写如下内容:

    {% extends "admin/change_form.html" %}
    {% block field_sets %}
         {# your modification here #}
    {% endblock %}
    
  2. 加载您的页面,您应该会看到更改

【讨论】:

  • 在不复制所有块的情况下扩展主“index.html”模板仍然不够。一种解决方案是将一些../ 写入“扩展”路径并指定更独特的原始路径{% extends "../../admin/templates/admin/index.html" %}link to answer
  • 我认为在 TEMPLATES 中我们应该使用 'DIRS': [os.path.join(BASE_DIR, 'templates')],
  • 这是完美说明 SO 中的缺陷的线程类型。框架得到更新,问题不再相关,它实际上是对正确路径的威慑。很好的答案在这里。 RTFM 孩子们。
  • 感谢您的回答。除了“这个文件的位置不重要。”,一切都很好。
【解决方案3】:

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

例如

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

admin.site.index_template = 'admin/my_custom_index.html'
admin.autodiscover()

并将您的模板放在&lt;appname&gt;/templates/admin/my_custom_index.html

【讨论】:

  • 太棒了!这样做可以让您从 my_custom_index.html 执行 {% extends "admin/index.html" %} 并在不复制它的情况下引用 django 管理模板。谢谢。
  • @Semmel 应该将此标记为正确答案,因为它是使用内置 django 功能且不需要使用自定义模板加载器的最简单方法。
【解决方案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】:

    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 子文件夹) 我没有足够的声誉来评论程的帖子,这就是为什么我不得不把它写成新的答案。

    【讨论】:

    • 感谢您的反馈 hyneker 我希望我的回答现在更清楚、更直截了当。
    • 是的,知道可以在项目级别自定义模板很有用,即使其中一些模板可以在应用程序级别进行选择性更改。
    【解决方案6】:

    我在官方 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/
    

    这是你需要做的:

    1. 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()
      

      确保在您的应用程序的admin.py 中导入custom_admin_site 并在其上注册您的模型,以便在您的自定义管理站点上显示它们(如果您愿意的话)。

    2. mysite/apps.py中,创建AdminConfig的子类,并将上一步中的default_site设置为admin.CustomAdminSite

      from django.contrib.admin.apps import AdminConfig
      
      
      class CustomAdminConfig(AdminConfig):
          default_site = 'admin.CustomAdminSite'
      
    3. mysite/settings.py 中,将INSTALLED_APPS 中的django.admin.site 替换为apps.CustomAdminConfig(您在上一步中的自定义管理应用配置)。

    4. mysite/urls.py 中,将管理员 URL 中的 admin.site.urls 替换为 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)),
          ...
      ]
      
    5. templates 目录中创建要修改的模板,保持docs 中指定的默认Django 管理模板目录结构。例如,如果您要修改 admin/index.html,请创建文件 templates/admin/index.html

      现有的所有模板都可以通过这种方式进行修改,其名称和结构可以在Django's source code中找到。

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

      例如,如果您想保持一切原样但想覆盖 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 %}
      

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

    【讨论】:

    • 你有这方面的资料或文档吗?
    • 除了我在第 5 点中添加的两个参考之外,不,我没有其他任何东西。
    【解决方案7】:

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

    templates/admin/change_form.html

    {% extends 'django_admin/change_form.html' %}
    
    Your stuff here
    

    如果您担心库存模板是最新的,您可以将它们包含在 svn externals 或类似内容中。

    【讨论】:

    • 使用 svn externals 是个好主意。这带来的问题是我所有的翻译人员都将翻译所有这些模板(因为 makemessages 将从所有管理模板中收集翻译字符串),如果您使用多种语言,这会增加很多额外的工作。也许有办法从 makemessages 中排除这些模板?
    • --ignore 参数与makemessages 一起使用。见:docs.djangoproject.com/en/dev/ref/django-admin/#makemessages
    • 我认为另一个答案更适合我的需要。但我喜欢您的解决方案,并认为如果您不想弄乱您的模板加载器,这是一个不错的选择。
    【解决方案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 文件夹的符号链接:

      ln -s /usr/local/lib/python2.7/dist-packages/django/contrib/admin/templates/admin/ templates/django_admin
      

      如您所见,这取决于 python 版本和 Django 安装的文件夹。因此,将来或在生产服务器上,您可能需要更改路径。

      【讨论】:

        【解决方案10】:

        This 站点有一个简单的解决方案,适用于我的 Django 1.7 配置。

        FIRST: 在项目的 template/ 目录中创建一个名为 admin_src 的符号链接,指向已安装的 Django 模板。对于在 Dreamhost 上使用 virtualenv 的我来说,我的“源”Django 管理模板位于:

        ~/virtualenvs/mydomain/lib/python2.7/site-packages/django/contrib/admin/templates/admin
        

        SECOND:在templates/中创建一个admin目录

        所以我的项目的模板/目录现在看起来像这样:

        /templates/
           admin
           admin_src -> [to django source]
           base.html
           index.html
           sitemap.xml
           etc...
        

        第三个:在您的新模板/管理/目录中创建一个包含以下内容的 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 文件夹中。

        完成。很简单。

        【讨论】:

          【解决方案11】:

          您可以使用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):”之后省略了一个斜杠。也许信誉更好的人可以修复链接并删除此注释。

          【讨论】:

          猜你喜欢
          • 2011-12-07
          • 2013-01-23
          • 2017-04-10
          • 2011-04-27
          • 2012-06-23
          • 2017-01-27
          • 2014-05-10
          • 2018-10-22
          • 2019-05-02
          相关资源
          最近更新 更多