如何在不新建应用的前提下为Django Admin的模型创建子分类
Django Admin 单应用内模型子分类实现方案
无需新建应用,通过自定义AdminSite逻辑 + 小幅修改模板即可实现你要的层级展示效果。
实现原理
通过扩展Django原生AdminSite的get_app_list方法,给单个应用下的模型添加自定义逻辑分组,再修改管理后台首页模板识别分组并按层级渲染。
具体实现步骤
1. 自定义AdminSite并添加分组逻辑
在你的MyApp的admin.py中添加如下代码:
from django.contrib import admin from .models import foo, bar class CustomAdminSite(admin.AdminSite): site_header = "管理后台" def get_app_list(self, request, app_label=None): # 读取原生生成的应用列表 app_list = super().get_app_list(request, app_label) for app in app_list: # 定位到你的目标应用,注意是应用的小写标签名 if app['app_label'] == 'myapp': # 按自定义分组归类模型 group_map = {} for model in app['models']: # 读取模型Admin配置的分组名,未配置的默认归入其他分组 group_name = getattr(model['admin'], 'admin_group', '其他') if group_name not in group_map: group_map[group_name] = { "name": group_name, "models": [] } group_map[group_name]['models'].append(model) # 用分组列表替换原应用下的模型列表 app['models'] = list(group_map.values()) return app_list # 配置模型的Admin并指定所属分组 class FooAdmin(admin.ModelAdmin): # 对应你要的第一个子分类名称 admin_group = "第一个模型名称" class BarAdmin(admin.ModelAdmin): # 对应你要的第二个子分类名称 admin_group = "第二个模型名称" # 用自定义AdminSite注册模型 custom_admin = CustomAdminSite(name="custom_admin") custom_admin.register(foo, FooAdmin) custom_admin.register(bar, BarAdmin)
2. 修改项目路由配置
在项目根目录的urls.py中,把默认的admin路由替换为自定义的AdminSite路由:
from django.urls import path from MyApp.admin import custom_admin urlpatterns = [ # 替换原有的path('admin/', admin.site.urls) path('admin/', custom_admin.urls), ]
3. 重写Admin首页模板支持层级渲染
- 在你的项目
templates目录下新建admin文件夹 - 从Django源码的
django/contrib/admin/templates/admin/index.html复制原模板文件到刚才新建的admin目录下 - 修改模板中遍历应用模型的代码块,调整为支持分组渲染:
把原来遍历app.models的部分替换为如下内容:
{% for item in app.models %} {% if item.models %} <!-- 分组标题 --> <tr class="model-group"> <th colspan="3"><strong>{{ item.name }}</strong></th> </tr> {% for model in item.models %} <tr> {% if model.admin_url %} <th scope="row" style="padding-left: 2em;"><a href="{{ model.admin_url }}">{{ model.name }}</a></th> {% else %} <th scope="row" style="padding-left: 2em;">{{ model.name }}</th> {% endif %} {% if model.add_url %} <td><a href="{{ model.add_url }}" class="addlink">新增</a></td> {% else %} <td></td> {% endif %} {% if model.admin_url and show_changelinks %} {% if model.view_only %} <td><a href="{{ model.admin_url }}" class="viewlink">查看</a></td> {% else %} <td><a href="{{ model.admin_url }}" class="changelink">修改</a></td> {% endif %} {% else %} <td></td> {% endif %} </tr> {% endfor %} {% else %} <!-- 无分组的普通模型 --> <tr> {% if item.admin_url %} <th scope="row"><a href="{{ item.admin_url }}">{{ item.name }}</a></th> {% else %} <th scope="row">{{ item.name }}</th> {% endif %} {% if item.add_url %} <td><a href="{{ item.add_url }}" class="addlink">新增</a></td> {% else %} <td></td> {% endif %} {% if item.admin_url and show_changelinks %} {% if item.view_only %} <td><a href="{{ item.admin_url }}" class="viewlink">查看</a></td> {% else %} <td><a href="{{ item.admin_url }}" class="changelink">修改</a></td> {% endif %} {% else %} <td></td> {% endif %} </tr> {% endif %} {% endfor %}
注意事项
- 该方案为逻辑层面的分组,不会修改模型所属应用,也不需要新增数据库表或应用
- 多个模型可以分配到同一个分组,分组名称可根据需求任意修改
- 若需要给分组添加折叠、排序等功能,可自行在模板中添加对应的CSS和JS逻辑实现
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

