Django Xadmin 官方文档 之五 Xadmin 插件制作
欢迎大家扫码关注我的微信公众号:
目录
- 一、插件原理
- 模板插件
- 二、插件实例
- 三、插件开发
- 四、插件规范
一、插件原理
Xadmin 的插件系统架构设计一定程度上借鉴了 wordpress
的设计。 想要了解 Xadmin 的插件系统架构首先需要了解 Xadmin AdminView
的概念。 简单来说, 就是 Xadmin 系统中每一个页面都是一个 AdminView
对象返回的 HttpResponse
结果。 Xadmin 的插件系统做的事情其实就是在 AdminView
运行过程中改变其执行的逻辑, 或是改变其返回的结果, 起到修改或增强原有功能的效果。 下面让我们看看整个插件从制作完成到实际运行的整个过程。
首先需要创建自己的插件类, 插件类继承 BaseAdminPlugin
:
class HelloWorldPlugin(BaseAdminPlugin):...
开发好的插件首先要注册到 Xadmin 中, 示例代码如下:
# ListAdminView 是 Model 列表页面
xadmin.site.register_plugin(HelloWorldPlugin, ListAdminView)
其中插件的注册和使用可以参看 xadmin.sites.AdminSite.register_plugin()
。
当将插件注册到 Xadmin 后, Xadmin 在创建 AdminView
实例的时候会将该插件放入实例的 plugins
属性。 当 AdminView
在处理请求 时, 会首先逐个调用 plugins
中插件的 init_request()
方法, 插件在该方法中一般进行初始化的操作并且返回一个 Boolean 值告诉 AdminView
是否需要加载该插件。 当 init_request()
方法返回值为 False
时, AdminView
不会加载该插件。 实例如下:
class HelloWorldPlugin(BaseAdminPlugin):say_hello = False# 初始化方法根据 ``say_hello`` 属性值返回def init_request(self, *args, **kwargs):return bool(self.say_hello)
在以上实例中, 插件根据自身的 say_hello
属性来决定是否让自己被加载。 您可能会迷惑, say_hello
属性看起来一直会是 False
呀, 那样这个插件不是永远不会被加载? 其实 Xadmin 在创建插件实例的时候会将 OptionClass
的同名属性替换插件的属性。 这样, 在不同的 OptionClass
下会有不同的插件结果, 实例如下:
class ListAdminView(ModelAdminView):# 可以被插件截获或修改的方法使用该装饰器装饰@filter_hookdef get_context(self):...
使用 filter_hook()
装饰的方法执行过程中会根据一定原则执行插件中的同名方法, 具体信息查考该装饰器的文档内容。
xadmin.views.base.filter_hook(func)表明 AdminView 的方法可以被插件插入的装饰器。 执行使用了该装饰器的方法时, 会按照以下过程执行:1. 首先将实例的 plugins 属性取出, 取出含有同样方法名的插件;2. 按照插件方法的 priority 属性排序;3. 顺序执行插件方法, 执行插件方法的规则:如果插件方法没有参数,AdminView 方法的返回结果不为空则抛出异常;如果插件方法的第一个参数为 __ , 则 AdminView 方法将作为第一个参数传入, 注意, 这时还未执行该方法, 在插件中可以通过 __() 执行, 这样就可以实现插件在 AdminView 方法执行前实现一些自己的逻辑, 例如:def get_context(self, __):c = {'key': 'value'}c.update(__())return c如果插件方法的第一个参数不为 __ , 则执行 AdminView 方法, 将结果作为第一个参数传入;4. 最终将插件顺序执行的结果返回;
根据该装饰器的执行原则, 如果我们想修改上面示例中 ListAdminView
的 get_context
的返回值, 可以在插件中实现如下代码:
class HelloWorldPlugin(BaseAdminPlugin):# 在插件中加入同名方法,修改 ListAdminView 的 get_context 返回的值def get_context(self, context):context.update({'hello_target': 'World!!'})return context
如果我们希望插件在 AdminView
的方法前执行, 或是完全使用自己的方法替代 AdminView
的方法可以这样:
class HelloWorldPlugin(BaseAdminPlugin):# 第一个参数为 __ 。这样 __ 即为 ListAdminView 的 get_context 方法本身, 注意, 这时还没有执行这个方法。def get_context(self, __):context = {'hello_target': 'World!!'}# 我们可以在任何时候执行 AdminView 的方法, 或是根本不执行context.update(__())return context
至此, 加入的插件就实现了对 AdminView
方法的完全控制。
模板插件
我们知道, Django 中一个完整的 View 是包含模板的, 模板用来生成 View 最终返回的 HTML 内容。 当然, 插件也可以在模板中插入自己的内容。 我们来看看具体如何实现。
首先让我们来看看 Xadmin 中的模板代码示例片段 (change_list.html):
{% load xadmin %}
...
<form id="changelist-form" action="" method="post"{% view_block 'result_list_form' %}>{% csrf_token %}{% view_block 'results_top' %}<div class="results">{% if results %}...
其中的 view_block Tag 即为插件的插入点。 插件可以在自己的插件类中使用 block_ + 插入点名称
方法将 HTML 片段插入到页面的这个位置, 示例如下:
class HelloWorldPlugin(BaseAdminPlugin):# context 即为 TemplateContext, nodes 参数包含了其他插件的返回内容。# 您可以直接返回 HTML 片段, 或是将内容加入到 nodes 参数中def block_results_top(self, context, nodes):return s"<div class='info'>Hello %s</div>" % context['hello_target']
二、插件实例
下面让我们来看一个 Xadmin 中完整的插件实例:
from django.template import loaderfrom xadmin.sites import site
from xadmin.views import BaseAdminPlugin, ListAdminViewREFRESH_VAR = '_refresh'# 该插件实现了一个列表页面刷新器的效果
class RefreshPlugin(BaseAdminPlugin):# 用户可以定制刷新的频率,可以传入多个值。该属性会被 ``OptionClass`` 的同名属性替换refresh_times = []def init_request(self, *args, **kwargs):# 根据用户是否制定了刷新器来决定是否启动该插件return bool(self.refresh_times)# 插件拦截了返回 Media 的方法,加入自己需要的 js 文件。def get_media(self, media):if self.request.GET.get(REFRESH_VAR):# 当页面处于自动刷新状态时,加入自己的 js 制定刷新逻辑media.add_js([self.static('xadmin/js/refresh.js')])return media# Block Views# 在页面中插入 HTML 片段,显示刷新选项。def block_top_toolbar(self, context, nodes):current_refresh = self.request.GET.get(REFRESH_VAR)context.update({'has_refresh': bool(current_refresh),'clean_refresh_url': self.admin_view.get_query_string(remove=(REFRESH_VAR,)),'current_refresh': current_refresh,'refresh_times': [{'time': r,'url': self.admin_view.get_query_string({REFRESH_VAR: r}),'selected': str(r) == current_refresh,} for r in self.refresh_times],})# 可以将 HTML 片段加入 nodes 参数中nodes.append(loader.render_to_string('xadmin/blocks/refresh.html', context_instance=context))
# 注册插件
site.register_plugin(RefreshPlugin, ListAdminView)
最后不要忘记在适当的地方加载该代码, 让其执行。 一般情况下, 你可以将其写到 adminx.py 文件中, 这样, 只要您的 APP 加入到 Django Settings 的 INSTALL_APPS 中, Xadmin 就会自动执行 app 下的 adminx.py 文件。
三、插件开发
了解了插件的运行原理后我们就可以开发自己的插件了。 首先我们需要了解插件类中的实用方法。 因为插件是继承 BaseAdminPlugin
类, 而该类继承自 BaseAdminObject
, 所以这两个类的方法都可以在插件中使用。
Xadmin 在创建插件时会自动注入以下属性到插件实例中:
- request: Http Request
- user: 当前 User 对象
- args: View 方法的 args 参数
- kwargs: View 方法的 kwargs 参数
- admin_view: AdminView 实例
- admin_site: Xadmin 的 admin_site 对象实例
如果 AdminView
是 ModelAdminView
的子类, 还会自动注入以下属性:
- model: Model 对象
- opts: Model 的 _meta 属性
接下来您应该考虑打算制作什么功能的插件了。 不同功能的插件可能需要注册到不同的 AdminView
上, Xadmin 系统中主要的 AdminView
有:
- BaseAdminView: 所有
AdminView
的基础类, 注册在该 View 上的插件可以影响所有的AdminView
; - CommAdminView: 用户已经登录后显示的 View, 也是所有登录后 View 的基础类。 该 View主要作用是创建了 Xadmin 的通用元素, 例如: 系统菜单、 用户信息等。 插件可以通过注册该 View 来修改这些信息;
- ModelAdminView: 基于 Model 的
AdminView
的基础类,注册的插件可以影响所有基于 Model 的 View; - ListAdminView: Model 列表页面 View;
- ModelFormAdminView: Model 编辑页面 View;
- CreateAdminView: Model 创建页面 View;
- UpdateAdminView: Model 修改页面 View;
- DeleteAdminView: Model 删除页面 View;
- DetailAdminView: Model 详情页面 View;
选择好目标 AdminView
后就要在自己的插件中编写方法来修改或增强这些 AdminView
。 其中每个 AdminView
可以拦截的方法及其介绍请参看各 AdminView
的文档。
四、插件规范
文档模板:
"""
Name
======作者
----该插件的作者信息功能
----描述插件的主要功能截图
----.. image:: /images/plugins/action.png使用
----描述插件的使用方法, 以及使用示例.版本
----描述插件的版本信息API
---
.. autoclass:: XXX"""
【“插件规范” 应该是官网为了规范开发者制作插件的格式而统一制定的。 不知道理解的对不对, 希望能得到大神的指点。】
Django Xadmin 官方文档 之五 Xadmin 插件制作相关推荐
- Django入门 | 官方文档带你快速入门
初识 Django 设计模型 应用数据模型 享用便捷的 API 一个动态管理接口:并非徒有其表 规划 URLs 编写视图 设计模板 这仅是基本入门知识 快速安装指南 安装 Python 设置数据库 安 ...
- 喜大普奔!Django官方文档终于出中文版了
喜大普奔!Django官方文档终于出中文版了 文章来源:企鹅号 - Crossin的编程教室 昨天经 Sur 同学告知才发现,Django 官方文档居然支持中文了! 之所以让我觉得惊喜与意外,是因为: ...
- 【官方文档】Fluent Bit 数据管道之过滤插件(Kubernetes)
文章目录 1. 配置参数 2. 处理 'log' 值 3. Kubernetes Annotations 3.1. Pod 定义中的 annotations 示例 3.1.1. 建议一个解析器 3.1 ...
- 【官方文档】Fluent Bit 数据管道之输入插件(Tail)
文章目录 1. 配置参数 2. 多行支持 2.1. 多行核心 (v1.8) 2.2. 多行和容器 (v1.8) 2.3. 旧的多行配置参数 2.4. 旧的 Docker 模式配置参数 3. 入门指南 ...
- 【官方文档】Fluent Bit 数据管道之过滤插件(Parser)
文章目录 1. 配置参数 2. 配置文件 3. 保留原始字段 3.1. Reserve_Data 3.2. Preserve_Key 官方文档地址: Parser Parser 过滤器插件允许解析事件 ...
- SlidesJS基本使用方法和官方文档解释 【Jquery幻灯片插件 Jquery相册插件】
SlidesJS基本使用方法和官方文档解释 [Jquery幻灯片插件 Jquery相册插件] 标签: jquery文档functionstringdiv相册 2012-04-19 15:23 3931 ...
- Django安装教程——4.0(官方文档版)
Django安装教程--4.0(官方文档版) Django安装教程--4.0(官方文档版) 概要 对Django的认识 应用数据模型 使用PythonAPI 一个动态管理接口 规划URLs 编写视图 ...
- Vue CLI 官方文档(一)@vue/cli、@vue/cli-service、插件和 Preset
Vue CLI 官方文档(一)@vue/cli.@vue/cli-service.插件和 Preset 文章目录 Vue CLI 官方文档(一)@vue/cli.@vue/cli-service.插件 ...
- 爆肝1个多月,严选10大热门静态博客框架,官方文档、教学视频、经典案例、热门插件一应俱全,强烈建议收藏
[文章编号 t001] 凌晨 12 点,我有一位朋友,在电话里,气愤地说他的博客文章又被平台删掉了. 我很好奇为什么,原来是他在某平台发布了一篇技术类原创文章,读者都比较喜欢.后来,他把这篇文章转发到 ...
最新文章
- Thinkpad W520 完美安装Ubuntu14.04LTS
- 使用Xcode和Instruments调试解决iOS内存泄露(转)
- 【人脸表情识别】情绪识别相关会议、比赛汇总(2018-2020)
- [PAT乙级]1021 个位数统计
- 来了!云栖大会都能看到什么?
- php5.5.* mysqlnd驱动安装
- 可视化idea_给IDEA换个酷炫的主题,这个有点哇塞啊!
- 【力扣】NO.13.罗马数字转整数
- python语言中的缩进是什么意思_python编程中的缩进是什么意思
- python脚本编程基础读后感_Python入门经典的读后感10篇
- HTML5调整图像垂直边距,77.通过vspace和hspace属性可以分别调整图像的垂直边距和水平边距。()()...
- html5图片在线剪辑,Web端裁剪图片方法
- 计算机开机检测dhcp,电脑开机显示dhcp是什么意思
- DL中常用的三种K-Lipschitz技术
- K210模块使用简介+Win10下本地训练模型
- 【MySQL】插入语句汇总
- BUUCTF Reverse前五题解题记录
- 初学者如何查阅自然语言处理(NLP)领域学术资料
- 【Python实战】--词云制作
- “元宇宙”会对教育产生什么影响?你想知道的都在这……
热门文章
- 你会正确卸载数据库吗?
- 浅谈java使用指定字符集编码,以及常见的字符集
- Python将csv文件以某列为条件分类切割
- redis笔记-常用命令篇(采用与《redis入门指南》)
- Python入门之基础知识(三)
- 学习FPGA的网站推荐
- FPGA经验谈系列文章——FPGA资源评估
- Virustotal——上传样本保存扫描结果
- 包含高知漫画家珍贵作品的艺术项目“NAKED Manga Mappin’!”3月6日(周五)起在高知龙马机场展出
- 考研热催生百亿市场,行业老兵文都教育的“冷思考” ——和大学生交朋友