欢迎大家扫码关注我的微信公众号:

目录

  • 一、插件原理
    • 模板插件
  • 二、插件实例
  • 三、插件开发
  • 四、插件规范

一、插件原理

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. 最终将插件顺序执行的结果返回;

根据该装饰器的执行原则, 如果我们想修改上面示例中 ListAdminViewget_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 对象实例

如果 AdminViewModelAdminView的子类, 还会自动注入以下属性:

  • 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 插件制作相关推荐

  1. Django入门 | 官方文档带你快速入门

    初识 Django 设计模型 应用数据模型 享用便捷的 API 一个动态管理接口:并非徒有其表 规划 URLs 编写视图 设计模板 这仅是基本入门知识 快速安装指南 安装 Python 设置数据库 安 ...

  2. 喜大普奔!Django官方文档终于出中文版了

    喜大普奔!Django官方文档终于出中文版了 文章来源:企鹅号 - Crossin的编程教室 昨天经 Sur 同学告知才发现,Django 官方文档居然支持中文了! 之所以让我觉得惊喜与意外,是因为: ...

  3. 【官方文档】Fluent Bit 数据管道之过滤插件(Kubernetes)

    文章目录 1. 配置参数 2. 处理 'log' 值 3. Kubernetes Annotations 3.1. Pod 定义中的 annotations 示例 3.1.1. 建议一个解析器 3.1 ...

  4. 【官方文档】Fluent Bit 数据管道之输入插件(Tail)

    文章目录 1. 配置参数 2. 多行支持 2.1. 多行核心 (v1.8) 2.2. 多行和容器 (v1.8) 2.3. 旧的多行配置参数 2.4. 旧的 Docker 模式配置参数 3. 入门指南 ...

  5. 【官方文档】Fluent Bit 数据管道之过滤插件(Parser)

    文章目录 1. 配置参数 2. 配置文件 3. 保留原始字段 3.1. Reserve_Data 3.2. Preserve_Key 官方文档地址: Parser Parser 过滤器插件允许解析事件 ...

  6. SlidesJS基本使用方法和官方文档解释 【Jquery幻灯片插件 Jquery相册插件】

    SlidesJS基本使用方法和官方文档解释 [Jquery幻灯片插件 Jquery相册插件] 标签: jquery文档functionstringdiv相册 2012-04-19 15:23 3931 ...

  7. Django安装教程——4.0(官方文档版)

    Django安装教程--4.0(官方文档版) Django安装教程--4.0(官方文档版) 概要 对Django的认识 应用数据模型 使用PythonAPI 一个动态管理接口 规划URLs 编写视图 ...

  8. Vue CLI 官方文档(一)@vue/cli、@vue/cli-service、插件和 Preset

    Vue CLI 官方文档(一)@vue/cli.@vue/cli-service.插件和 Preset 文章目录 Vue CLI 官方文档(一)@vue/cli.@vue/cli-service.插件 ...

  9. 爆肝1个多月,严选10大热门静态博客框架,官方文档、教学视频、经典案例、热门插件一应俱全,强烈建议收藏

    [文章编号 t001] 凌晨 12 点,我有一位朋友,在电话里,气愤地说他的博客文章又被平台删掉了. 我很好奇为什么,原来是他在某平台发布了一篇技术类原创文章,读者都比较喜欢.后来,他把这篇文章转发到 ...

最新文章

  1. Thinkpad W520 完美安装Ubuntu14.04LTS
  2. 使用Xcode和Instruments调试解决iOS内存泄露(转)
  3. 【人脸表情识别】情绪识别相关会议、比赛汇总(2018-2020)
  4. [PAT乙级]1021 个位数统计
  5. 来了!云栖大会都能看到什么?
  6. php5.5.* mysqlnd驱动安装
  7. 可视化idea_给IDEA换个酷炫的主题,这个有点哇塞啊!
  8. 【力扣】NO.13.罗马数字转整数
  9. python语言中的缩进是什么意思_python编程中的缩进是什么意思
  10. python脚本编程基础读后感_Python入门经典的读后感10篇
  11. HTML5调整图像垂直边距,77.通过vspace和hspace属性可以分别调整图像的垂直边距和水平边距。()()...
  12. html5图片在线剪辑,Web端裁剪图片方法
  13. 计算机开机检测dhcp,电脑开机显示dhcp是什么意思
  14. DL中常用的三种K-Lipschitz技术
  15. K210模块使用简介+Win10下本地训练模型
  16. 【MySQL】插入语句汇总
  17. BUUCTF Reverse前五题解题记录
  18. 初学者如何查阅自然语言处理(NLP)领域学术资料
  19. 【Python实战】--词云制作
  20. “元宇宙”会对教育产生什么影响?你想知道的都在这……

热门文章

  1. 你会正确卸载数据库吗?
  2. 浅谈java使用指定字符集编码,以及常见的字符集
  3. Python将csv文件以某列为条件分类切割
  4. redis笔记-常用命令篇(采用与《redis入门指南》)
  5. Python入门之基础知识(三)
  6. 学习FPGA的网站推荐
  7. FPGA经验谈系列文章——FPGA资源评估
  8. Virustotal——上传样本保存扫描结果
  9. 包含高知漫画家珍贵作品的艺术项目“NAKED Manga Mappin’!”3月6日(周五)起在高知龙马机场展出
  10. 考研热催生百亿市场,行业老兵文都教育的“冷思考” ——和大学生交朋友