怎么解决django的admin后台⼆级菜单导航栏的排序问题?
⽂章⽬录
问题背景
  当我们使⽤django的admin来做后台管理时,会有种如鱼得⽔的感觉,通过可视化的页⾯,开发⼈员能够轻松地管理数据库⾥的数据,问题来了,在实际开发中,需要管理的model可达到到上百个,如果不能够对菜单的顺序进⾏管理,那么当我们去寻需要的model时,会⾮常的吃⼒,因为model多了就会显得杂乱⽆章,本⽂针对在jango的admin后台菜单导航栏的排序问题进⾏探讨!
1.分析admin.site.index
  ⾸先让我们看⼀下admin.site.index⽅法的源码,该⽅法⽤来给admin后台返回所有注册到admin后台的apps,即应⽤。
@never_cache
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 = _app_list(request)
context =dict(
self.each_context(request),
title=self.index_title,
app_list=app_list,
)
context.update(extra_context or{})
request.current_app = self.name
return TemplateResponse(request, self.index_template or'admin/index.html', context)
通过index⽅法返回的TemplateResponse,我们可以拿到导航栏⾥的所有注册到admin后台的apps。
app_list = t_data['app_list']
获取到导航栏结构,对应的数据结构如下, 其中student为我在polls应⽤下定义的model:
[{
'name':'Authentication and Authorization',
'app_label':'auth',
'app_url':'/admin/auth/',
'has_module_perms':True,
'models':[{
'name':'Groups',
'object_name':'Group',
'perms':{
'add':True,
'change':True,
'delete':True
},
'admin_url':'/admin/auth/group/',
'add_url':'/admin/auth/group/add/'
},{
'name':'Users',
'object_name':'User',
'perms':{
'add':True,
'change':True,
'delete':True
},
'admin_url':'/admin/auth/user/',
'add_url':'/admin/auth/user/add/'
}]
},{
'name':'Polls',
'app_label':'polls',
'app_url':'/admin/polls/',
'has_module_perms':True,
'models':[{
'name':'学⽣',
'object_name':'Student',
'perms':{
'add':True,
'change':True,
'delete':True
},
'admin_url':'/admin/polls/student/',
'add_url':'/admin/polls/student/add/'
}]
}]
可以发现,我们应⽤注册的model都到了app_label=="polls"⾥⾯,具体的Model信息放到了models属性⾥, 结构如下
'models':[{
'name':'学⽣',
'object_name':'Student',
'perms':{
'add':True,
'change':True,
'delete':True
},
'admin_url':'/admin/polls/student/',
'add_url':'/admin/polls/student/add/'
}]
  由上述可以发现,如果我能够调整⾥⾯Models列表⾥的元素顺序,那么在admin后台显⽰出导航栏的顺序也会发⽣变化。
2. 导航栏排序实现原理
  定义的app的顺序为: User , Student,Entry, 放到apps_index列表⾥。 然后通过⾃定义model放到apps_index列表⾥,遍历models 列表,从apps_index列表⾥出对应的model顺序,同时⽤新的model去放[{pos: 原先的model },…], 将得到的新的model,按照pos从⼩到⼤来进⾏排序, 最后只要获取到model⾥的属性, 将获取到的models重新赋值给app_list原有的models。
app_list = t_data['app_list']
app_list.sort(key=lambda r: find_app_index(r['app_label']))
print("app_list:", app_list)
for app in app_list:
##polls为app的名称
if app["app_label"]=="polls":
# 按照指定顺序排序
models = app["models"]
new_models =[]
for i in models:
model_name = i["object_name"]
pos = apps_index.index(model_name)
new_models.append({"pos": pos,"model": i})
new_models.sort(key=lambda s: s["pos"])
# app['models'].sort(key=lambda x: find_model_index(x['name']))
models =[x["model"]for x in new_models]
app["models"]= models
print("models:", models)
导航列表:
apps_index =["User","Student","Entry"]
3.完整代码
ib import admin
from django.apps import apps
dels import Student, User, Entry
# Register your models here.
class FlatPageAdmin(admin.ModelAdmin):
fieldsets =(
(None,{
'fields':('url','title','content','sites')
}),
('Advanced options',{
'classes':('collapse',),
'fields':('registration_required','template_name'),
}),
)
class StudentAdmin(admin.ModelAdmin):
list_display =('name','birthday','amount')
search_fields =('name',)
class UserAdmin(admin.ModelAdmin):
list_display =["id"]
search_fields =["id"]
class EntryAdmin(admin.ModelAdmin):
list_display =["id"]
search_fields =["id"]
ister(Student, StudentAdmin)
ister(User, UserAdmin)
ister(User, UserAdmin)
ister(Entry, EntryAdmin)
# 指定导航顺序
apps_index =["User","Student","Entry"]
def find_app_index(app_label):
app = _app_config(app_label)
导航菜单main_menu_index =getattr(app,'main_menu_index',9999)
return main_menu_index
def index_decorator(func):
def inner(*args,**kwargs):
templateresponse = func(*args,**kwargs)
app_list = t_data['app_list']
app_list.sort(key=lambda r: find_app_index(r['app_label']))
print("app_list:", app_list)
for app in app_list:
if app["app_label"]=="polls":
# 按照指定顺序排序
models = app["models"]
new_models =[]
for i in models:
model_name = i["object_name"]
pos = apps_index.index(model_name)
new_models.append({"pos": pos,"model": i})
new_models.sort(key=lambda s: s["pos"])
# app['models'].sort(key=lambda x: find_model_index(x['name']))
models =[x["model"]for x in new_models]
app["models"]= models
print("models:", models)
return templateresponse
return inner
admin.site.index = index_decorator(admin.site.index)
admin.site.app_index = index_decorator(admin.site.app_index)
admin.site.site_header ="bingbing后台管理"
admin.site.site_title ='bingbing后台管理'
admin.site.index_title ='bingbing后台管理'
显⽰效果将会按照指定的导航列表⾥的顺序来展⽰ , 另外需要注意的是将注册的Model名称添加到 apps_index⾥即可!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。