如何在Django管理界面中覆盖CSS?

115

我想在 Django 管理员中更改某些 CSS,例如 base.css。是直接更改 Django 库更好呢?最佳的覆盖方式是什么?

9个回答

134
这取决于你想做什么。但首先:不要直接在Django管理界面中覆盖它。我认为你有两个合理的选择:
1. 如果你想更改管理员界面的外观,应该重写管理员模板。这在这里详细介绍:重写管理员模板。有时候你只需要扩展原始的管理员文件,然后在django/contrib/admin/templates/admin/base.html中覆盖类似于{% block extrastyle %}{% endblock %}的块。
2. 如果你的样式是针对特定模型的,你可以通过admin.py中的Media元类添加附加样式。请参见此处的示例:
class MyModelAdmin(admin.ModelAdmin):
    class Media:
        js = ('js/admin/my_own_admin.js',)    
        css = {
             'all': ('css/admin/my_own_admin.css',)
        }

1
事实上,需要更改的不仅是模型级别,而是整个网站本身。具体来说,是在base.css、ie.css等文件中进行更改。一种选择是将admin/base.html包含在我的应用程序中,并在admin/base.html文件中使用自定义的base.css。这样,我就必须将django管理界面的一些模板文件包含到自己的网站中。除此之外,还有更好的解决方案吗? - rajan sthapit
1
我不知道其他的。Django管理后台最终只是一个Django可重用应用程序。这也适用于任何其他可重用的应用程序。 - Torsten Engelbrecht
我注意到这里的js文件中列出了一个.css文件...那真的能够起作用吗?我试过,但是没成功。 - fastmultiplication
是的,你说得对。我犯了一个错误,并从Django文档中编辑了我的答案示例。 - Torsten Engelbrecht
用Eli Porter的话说,“你烤了最好的猫”。 - Rob Kwasowski
显示剩余2条评论

57
  • settings.py中,确保你的应用程序在INSTALLED_APPS中先于admin被列出。
  • 创建(your-app)/templates/admin/base_site.html并将<style>块放入{% block extrahead %}中。
{% extends "admin/base_site.html" %}
{% block extrahead %}
    <style>
        .field-__str__ {
            font-family: Consolas, monospace;
        }
    </style>
{% endblock %}

10
最佳答案。如果您希望避免在 INSTALLED_APPS 中将您的应用程序排在管理员之前,可以通过在基础项目中放置一个“模板”目录并在 settings.py 中引用它来实现: TEMPLATES = [ ...其他内容..., 'DIRS': [os.path.join(BASE_DIR, 'templates')], ] - RedPelle
太棒了!像魔法一样顺畅运行! - ozw1z5rd
如果您使用自定义身份验证用户模型并希望在admin.py中注销身份验证组模型,请确保在您的应用程序之前列出django.contrib.auth。 - Chris Fowl

35

我认为这个解决方案适用于管理员网站,这是最清晰的方式,因为它覆盖了base_site.html,而在升级Django时不会更改。

在您的模板目录中创建一个名为admin的文件夹,在其中创建一个名为base_site.html的文件。

在您的静态目录下创建一个名为admin-extra.css的文件,位于css目录下。

在其中编写所有您想要用于表单的自定义CSS,例如:body{background: #000;}

将以下内容粘贴到base_site.html中:

{% extends "admin/base.html" %}
{% load static from staticfiles %} # This might be just {% load static %} in your ENV

{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}

{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "css/admin-extra.css" %}" />{% endblock %}

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('Django administration') }}</a></h1>
{% endblock %}

{% block nav-global %}{% endblock %}

如评论中所述:确保你的应用在INSTALLED_APPS中排在admin应用之前,否则你的模板将无法覆盖django的

就是这样了!完成了。


6
谢谢,非常有效!如果无法正常工作,请确保您的应用在INSTALLED_APPS中排在管理应用程序之前,否则您的模板将无法覆盖Django的模板。 - Dirbaio
2
最佳答案和评论。更改管理页面的颜色实际上是非常困难的。阅读此答案和评论确实加深了我对其工作原理的理解。 - Daniel Butler
2
你怎么知道在升级 Django 时 base_site.html 模板不会改变呢?(我的意思是,虽然这个答案已经有三年了,但并不能保证它仍然适用) - Marv
@marv 如果你在源代码中查看底层实现,你会很容易地发现管理员架构是围绕这些特定名称构建的,尤其是在URL和模板渲染方面。继承类的类依赖于这些名称保持不变,除非Django框架进行了重大重新设计(即使如此,我也不会打赌这会改变)。根据Django路线图,至少在未来3年内,覆盖管理视图和管理URL以及覆盖基本模板的总体基本约定将保持不变。 - elad silver
2
这只是关于Django的一般知识,没有具体的来源证实吗?我并不怀疑你,只是想知道人们应该如何找出这种情况。 - Marv
显示剩余2条评论

29

我刚刚扩展了 admin/base.html 文件,以包含对我的自定义 CSS 文件的引用 - 放在最后。CSS 的美妙之处在于您不必修改现有的定义,只需重新定义即可。


19
在您的静态目录中创建一个static/admin/css/base.css文件。首先粘贴Django默认的管理界面CSS,然后在底部添加自定义内容。

9
如果你这样做,请确保在“INSTALLED_APPS”列表中把你的应用程序放在django.contrib.admin之前。否则,collectstatic将首先找到管理员的base.css文件,你的自定义版本将无法覆盖它。 - Dave
3
这不是一个好的长期解决方案。它只是复制/粘贴了很多代码,而且随着Django的升级,它也不会得到维护。 - mlissner
Django后台的任何样式更改基本上都是对代码的分叉。 Django的更新可能会导致您的自定义样式无法使用。我的建议是将自定义样式最小化,并将它们添加到Django默认样式的底部。这样,如果需要,您可以手动更新默认样式。 - Ryan Allen
@danny-w-adair上面的答案更好;保持了“DRY”的原则,但它仍然是Django代码的一个分支,可能会导致升级时的小问题。 - Ryan Allen

14
如果你希望拥有全局作用域,并且不想考虑覆盖模板,那么混入(mixin)对此非常有效。将以下代码放在您想要的任何地方即可:
class CSSAdminMixin(object):
    class Media:
        css = {
            'all': ('css/admin.css',),
        }

接下来,制作一个名为admin.css的CSS文件,并在其中添加你需要覆盖的样式,例如:

select[multiple] {
    resize: vertical;
}

然后,无论你想要的模型是什么,都要执行以下操作:

class MyModelAdmin(admin.ModelAdmin, CSSAdminMixin):

你将一切准备就绪。


我喜欢你的答案,但为什么不直接添加到MyModelAdmin中呢? - Goran
1
如果只有一个模型,你可以这样做,但如果对多个模型进行操作,会变得混乱不堪。 - mlissner

5

admin/css/changelists.css放在STATICFILES_DIRS文件夹中,它将使用该changelists.css代替默认的管理员样式表。


1

你可以在Django后台中覆盖base.css

例如,如下所示存在一个Person模型:

# "app1/models.py"

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

然后,下面展示的是Person管理员:
# "app1/admin.py"

from django.contrib import admin
from .models import Person

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    pass

然后,下面显示了Person管理员:

enter image description here

然后,将 django/contrib/admin/static/admin/css/base.css 中的 base.css 复制到您的虚拟环境下的 static/admin/app1/css/,如下所示:

django-project
 |-core
 |  └-settings.py
 |-app1
 |  |-models.py
 |  └-admin.py
 |-app2
 └-static
    └-admin
       └-app1
          └-css
             └-base.css # Here

然后在base.css中,将background: var(--header-bg);替换为background: black;,如下所示,在Person管理页面中将标题颜色更改为黑色:
/* "static/admin/app1/css/base.css" */

#header {
    width: auto;
    height: auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 40px;
    /* background: var(--header-bg); */
    background: black;
    color: var(--header-color);
    overflow: hidden;
}

首先,我会解释如何在“Person”管理页面中将标题颜色更改为黑色。
所以,请将“admin/app1/css/base.css”设置为Media class中的css,如下所示:
# "app1/admin.py"

from django.contrib import admin
from .models import Person

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    class Media:
        css = {    # ↓ ↓ ↓ ↓ ↓ ↓ Here ↓ ↓ ↓ ↓ ↓ ↓
            "all": ("admin/app1/css/base.css",)
        }      

然后,如下所示,在 Person 管理页面中将标题颜色更改为黑色:

enter image description here

而且,在下面显示的Animal管理界面中,标题颜色没有变成黑色。

enter image description here

接下来,我将解释如何在所有管理页面中将页眉颜色更改为黑色。
所以,请将位于您的虚拟环境中的/django/contrib/admin/templates/admin/base.htmlbase.html复制到/templates/admin/base.html,如下所示:
django-project
 |-core
 |  └-settings.py
 |-app1
 |  |-models.py
 |  └-admin.py
 |-app2
 |-static
 |  └-admin
 |     └-app1
 |        └-css
 |           └-base.css # Here
 └-templates
    └-admin
       └-base.html # Here

然后在base.html中,将admin/css/base.css替换为admin/app1/css/base.css{% static %}中:
# "templates/admin/base.html"

# ...
<title>{% block title %}{% endblock %}</title>
{# <link rel="stylesheet" href="{% block stylesheet %}{% static "admin/css/base.css" %}{% endblock %}"> #}
{# ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ Here ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ #}
<link rel="stylesheet" href="{% static "admin/app1/css/base.css" %}"> {# ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ Here ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ #}
{% block dark-mode-vars %}
#...

然后,如下所示,在PersonAnimal管理员中将标题颜色更改为黑色:

enter image description here

enter image description here


0

碰巧我在想要覆盖CSS时,将<style>标签放在{% block extrastyle %}{% endblock %}内部并没有起作用。主题支持提供了正确的方法。我所忽略的就是{{ block.super }} :-

{% extends 'admin/base.html' %}

{% block extrastyle %}{{ block.super }}
<style>
--- your style ---
--- properties here ---
</style>
{% endblock %}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接