概述
adminx官方文档对插件系统的描述如下:
Xadmin 的插件系统做的事情其实就是在
AdminView
运行过程中改变其执行的逻辑, 或是改变其返回的结果,起到修改或增强原有功能的效果。
在实际运用过程中,我们可以制作插件来给页面添加新的布局、按钮等,来为页面添加更多自定义功能。
插件的制作过程如下:
- 创建自己的插件类, 插件类继承
BaseAdminPlugin
:
1 | from xadmin.views import BaseAdminPlugin |
编写
MyCustomizePlugin
类将开发好的plugin注册到
AdminView
中:
1 | xadmin.site.register_plugin(MyCustomizePlugin, ListAdminView) |
开发过程说明
其实官方文档已经说明了大致过程了,但由于各种原因(好吧,可能是因为我比较笨〒▽〒),很难理解应用在实际的开发过程中。下面是消化理解后整理的过程,以备后续不时之需。
编写自定义plugin
在AdminView
的执行过程中,可以被插件截获或修改的方法使用filter_hook()
装饰。因此,可以查看要注册到的AdminView源码中使用该装饰器的方法。
init_request(self, *args, **kwargs)
插件在该方法中一般进行初始化的操作并且返回一个 Boolean 值告诉AdminView
是否需要加载该插件。当 init_request() 方法返回值为 False 时,AdminView
不会加载该插件。例如:
1 | mycustomize_allow = False |
若要在MyModelAdmin
中使用该插件,则可以在MyModelAdmin
中设置mycustomize_allow
值为True
block_xxx(self, context, nodes)
- context 即为 TemplateContext, nodes 参数包含了其他插件的返回内容。您可以直接返回 HTML 片段,或是将内容加入到 nodes 参数中
使用例子如下:
1 | def block_nav_menu(self, context, nodes): |
接下来是干货!!
get_media(self, media)
该方法可以用来添加额外的js/css文件。
1 | def get_media(self, media): |
get_context(self)
返回显示页面所需的 context 对象。
注册plugin
根据官方文档,有以下几种AdminView
:
-
所有
AdminView
的基础类,注册在该 View 上的插件可以影响所有的AdminView
-
用户已经登陆后显示的 View,也是所有登陆后 View 的基础类。该 View主要作用是创建了 Xadmin 的通用元素,例如:系统菜单,用户信息等。插件可以通过注册该 View 来修改这些信息。
-
基于 Model 的
AdminView
的基础类,注册的插件可以影响所有基于 Model 的 View。 -
Model 列表页面 View。
-
Model 编辑页面 View。
-
Model 创建页面 View。
-
Model 修改页面 View。
-
Model 删除页面 View。
-
Model 详情页面 View。
说明:注册语句可以直接在
adminx.py
中实现,也可以放在别的地方,然后导入到adminx.py
中即可。
举个栗子 + 大白话开发过程
举个例子。假设我要在Model 编辑页面上正文的导航条上加个菜单。那么,
- 声明这个插件类,继承
BaseAdminPlugin
- 因为我要在所有编辑页面上都加,也就是说创建页面和修改页面都要有,因此选择注册到
ModelFormAdminView
上。 - 声明插件类的
init_request
方法,添加一个属性xxx_allow
来决定要不要使用该插件。 4. 因为是要修改页面的,因此要找到插入点。有了上面的干货,发现插入点是{% view_block 'nav_menu' %} - 找到插入点了,编写
block_nav_menu
方法。使用context.update添加一些菜单信息,在我的xxx_template.html
模板里面要使用这些菜单信息来构建菜单。然后使用nodes.append(loader.render_to_string('/path/to/xxx_template.html', context=context))
添加渲染信息 - 当然,还要编写xxx_template.html啦。
- 决定不要在xxx_template.html中实现js,于是单独实现了一个js。这样的话,需要在插件类中实现
get_media
加入新的js,才能使我这个新的js对这个插件生效 - 最后,在我的modeladmin上面设置
xxx_allow=True
,从而使得此model使用该插件。