Django 修改后台models的名称和排序
2022-07-29 # django

要修改admin后台中models的名称非常简单,就是在models的元类中添加verbose_name_plural字段即可,而修改排序的其中一种方法也和这个字段有关。

1
2
class Meta:       
verbose_name_plural = ' 中文名称'

而要修改models在admin中的排序,有以下4种方法

  • 每个 APP model 里为 Meta 类下的 verbose_name_plural 字段添加 数字前缀或者英文空格 参考
  • 重写 admin/base.html 模板页面 参考
  • 重写 AdminSite 类的 index() 方法 参考
  • 重新 AdminSite 类的 get_app_list() 方法 参考

实测有用的,最简单的第一种方法就是往verbose_name_plural 这个字段中添加英文空格,空格加的越多排序越往上。这个方法的好处是可以随时方便地修改排序。算是一种dirty trick吧,admin本来就是给自己看的,管用没有副作用就行。

当然如果你非要装个B可以采用2-4的方法。本文再详细记录下第三种方法。算是学习下思路吧,但对解决本问题,除了复杂容易出错外,其实并没有什么卵用。

Django 源码 Admin 主页渲染的 app_list 列表是由 get_app_list() 方法按 字母排序 后返回的结果

所以只需要对 app_list 进行排序即可

https://docs.djangoproject.com/en/2.1/_modules/django/contrib/admin/sites/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def index(self, request, extra_context=None):
"""
Display the main admin index page, which lists all of the installed
apps that have been registered in this site.
"""
app_list = self.get_app_list(request)

context = {
**self.each_context(request),
'title': self.index_title,
'app_list': app_list,
**(extra_context or {}),
}

request.current_app = self.name

return TemplateResponse(request, self.index_template or 'admin/index.html', context)

首先参考官方文档覆盖 Django Admin 的 AdminSite 类:

https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#overriding-the-default-admin-site

项目名称 zerone

zerone/ 子目录下创建 zerone/admin.py 文件,重写 AdminSiteindex() 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from django.contrib import admin

class MyAdminSite(admin.AdminSite):

def index(self, request, extra_context=None):
if extra_context is None:
extra_context = {}

app_list = self.get_app_list(request)
app_dict = self._build_app_dict(request)

# dict_keys(['equipment', 'liveos', 'clone', 'oauth2_provider', 'auth'])
print(app_list, app_dict.keys())

extra_context['app_list'] = app_list
return super(MyAdminSite, self).index(request, extra_context)

创建 zerone/apps.py 文件,自定义 AdminConfig 配置名称:

1
2
3
4
from django.contrib.admin.apps import AdminConfig

class MyAdminConfig(AdminConfig):
default_site = 'zerone.admin.MyAdminSite'

使用刚在 zerone/apps.py 自定义的 APP 配置名称,替换默认的 django.contrib.admin

修改 zerone/settings.py

1
2
3
4
5
INSTALLED_APPS = [
...
'zerone.apps.MyAdminConfig', # replaces 'django.contrib.admin'
...
]

重写 AdminSiteindex() 方法之前,先查看一下默认 app_dict 包含的 所有 APP 名称:

1
2
3
4
5
app_list = self.get_app_list(request)
app_dict = self._build_app_dict(request)
print(app_list, app_dict.keys())

# dict_keys(['equipment', 'liveos', 'clone', 'oauth2_provider', 'auth'])

默认 get_app_list() 按照字母排序的 APP 顺序是:

1
2
3
4
5
'auth',
'oauth2_provider',
'clone',
'equipment',
'liveos'

然后根据上面显示的 所有 APP 名称,自定义 APP 的排序列表:

1
apps_order_list = ['equipment', 'liveos', 'clone', 'oauth2_provider', 'auth']

然后就是根据自定义的 apps_order_list 对默认的 app_list 进行排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from django.contrib import admin

apps_order_list = ['equipment', 'liveos', 'clone', 'oauth2_provider', 'auth']
apps_order_dict = { app: index for index, app in enumerate(apps_order_list) }

class MyAdminSite(admin.AdminSite):

def index(self, request, extra_context=None):
if extra_context is None:
extra_context = {}

app_list = self.get_app_list(request)
app_dict = self._build_app_dict(request)

# dict_keys(['equipment', 'liveos', 'clone', 'oauth2_provider', 'auth'])
print(app_dict.keys())

# https://stackoverflow.com/questions/15650348/sorting-a-list-of-dictionaries-based-on-the-order-of-values-of-another-list
# https://docs.python.org/3/howto/sorting.html
app_list.sort(key=lambda element_dict:apps_order_dict[element_dict["app_label"]])

# print(app_list)

extra_context['app_list'] = app_list
return super(MyAdminSite, self).index(request, extra_context)

DONE