八、xadmin自定义菜单栏顺序
xadmin默认是读取注册的app和所有注册到xadmin的mode来生成对应的菜单。
nav_menu[app_key] = {
'title': app_title,
'menus': [model_dict],
}
那么如何按照我们自定义的顺序显示菜单的排列顺序呢?
通过查看xadmin的源码,我们可以看出,xadmin的菜单显示分为两部:
1)注册
2)显示
所以对应的我们也可以有两种方式去自定义菜单的显示顺序:
1)在注册的时候让菜单按照我们想要显示的顺序注册并读取
这种方式,需要用到collections模块中的OrderedDict,默认xadmin注册用的是无序字典Dict
2)在读取的时候按需求自定义显示顺序,可以通过变量控制,这种方式相对而言更加的灵活
有了解决思路,那么要考虑的就是怎么样去实现代码功能了。
先说第一种,直接修改_register变量,这种修改方式是最简单的:
xadmin注册的时候,调用的是xadmin.site.register()函数,查看源码我们可以知道,最终是将注册的model信息存在了_register变量中,而_register变量是一个dict,dict是无序的。
但是秉着除非万不得已,我们尽量不要改变库的源码,所以我们需要在外面想办法去修改这个_register变量。
Django项目,在启动时,看wsgi文件中,首先是调用了我们的settings文件,所以我们可以在settings中导入xadmin,然后修改_register,这种修改方法是最简单的
接下来看看第二种修改方式,这种修改方式相对复杂一点,但是却很灵活,可以根据我们的需求随意定制
比如我们可以给菜单分组,排序等都可以按照这种方式进行。
最终读取并渲染到模板是在xadmin.views.bases中的CommAdminView类中完成的,我们可以自定义一个类,并在这个类中重写 get_nav_menu 方法,最后将我们自定义的类注册到xadmin即可
直接上源码:
其中红色部分是自定义用于分组和排序的变量,变量定义在每个app下的apps中
class GlobalSetting(object):
site_title = "上海诺行信息技术有限公司"
site_footer = "COPYRIGHT © 2010 - 2018 ALL RIGHTS RESERVED"
menu_style ="accordion"
apps_icons = {"home":"fa fa-home", "products":"", "companyintroduction":"", "certifications":"fa fa-certificate",
"contactus":"fa fa-phone", "forum":"","logisticinformation":"",
"sourcedownload":"fa fa-download","trade":"fa fa-shopping-cart","users":"fa fa-user",
"wechatuser":"fa fa-user", "knowledgebase":"fa fa-book","questionanswer":"fa fa-question-circle"}
@filter_hook
def get_nav_menu(self):
site_menu = list(self.get_site_menu() or [])
had_urls = []
def get_url(menu, had_urls):
if 'url' in menu:
had_urls.append(menu['url'])
if 'menus' in menu:
for m in menu['menus']:
get_url(m, had_urls)
get_url({'menus': site_menu}, had_urls)
nav_menu = OrderedDict()
menus_ = self.admin_site._registry.items()
for model, model_admin in menus_:
if getattr(model_admin, 'hidden_menu', False):
continue
app_label = model._meta.app_label
app_icon = None
model_dict = {
'title': smart_text(capfirst(model._meta.verbose_name_plural)),
'url': self.get_model_url(model, "changelist"),
'icon': self.get_model_icon(model),
'perm': self.get_model_perm(model, 'view'),
'order': model_admin.order,
}
if model_dict['url'] in had_urls:
continue
app_key = "app:%s" % app_label
if app_key in nav_menu:
nav_menu[app_key]['menus'].append(model_dict)
else:
# Find app title
app_title = smart_text(app_label.title())
if app_label.lower() in self.apps_label_title:
app_title = self.apps_label_title[app_label.lower()]
else:
appL = apps.get_app_config(app_label)
app_title = smart_text(apps.get_app_config(app_label).verbose_name)
# added by Fiona for menu ordering
if app_label == "auth":
app_index = len(menus_) - 1
elif app_label == "xadmin":
app_index = len(menus_) - 2
else:
app_index = appL.orderIndex_
# find app icon
if app_label.lower() in self.apps_icons:
app_icon = self.apps_icons[app_label.lower()]
nav_menu[app_key] = {
"orderIndex": app_index,
'title': app_title,
'menus': [model_dict],
}
app_menu = nav_menu[app_key]
if app_icon:
app_menu['first_icon'] = app_icon
elif ('first_icon' not in app_menu or
app_menu['first_icon'] == self.default_model_icon) and model_dict.get('icon'):
app_menu['first_icon'] = model_dict['icon']
if 'first_url' not in app_menu and model_dict.get('url'):
app_menu['first_url'] = model_dict['url']
for menu in nav_menu.values():
menu['menus'].sort(key=sortkeypicker(['order', 'title']))
nav_menu = list(nav_menu.values())
# nav_menu.sort(key=lambda x: x['title'])
# 左侧菜单自定义排序新增
nav_menu.sort(key=sortkeypicker(['orderIndex']))
site_menu.extend(nav_menu)
return site_menu
最终分组完成效果图如下: