xadmin的插件机制
xadmin的视图方法中如果加了@filter_hook 标记的都可以作为插件的钩子函数。
例如在ListAdminView类中有许多加了上述标记的方法,
@filter_hook
def get_context(self):
"""
Prepare the context for templates.
"""
self.title = _('%s List') % force_unicode(self.opts.verbose_name) model_fields = [(f, f.name in self.list_display, self.get_check_field_url(f))
for f in (self.opts.fields + self.get_model_method_fields()) if f.name not in self.list_exclude] new_context = {
'module_name': force_unicode(self.opts.verbose_name_plural),
'title': self.title,
'cl': self,
'model_fields': model_fields,
'clean_select_field_url': self.get_query_string(remove=[COL_LIST_VAR]),
'has_add_permission': self.has_add_permission(),
'app_label': self.app_label,
'brand_name': self.opts.verbose_name_plural,
'brand_icon': self.get_model_icon(self.model),
'add_url': self.model_admin_url('add'),
'result_headers': self.result_headers(),
'results': self.results()
}
context = super(ListAdminView, self).get_context()
context.update(new_context)
return context @filter_hook
def get_response(self, context, *args, **kwargs):
pass
在上述代码中,get_context方法被作为了一个插件钩子函数,当调用该方法的时候,会遍历ListAdminView注册的插件寻找插件中与get_context同名的方法,并把get_context
执行后的结果作为第二个参数(第一个参数是self)传给插件的get_context方法,于是我们可以在get_context方法返回结果前对其结果进行一些修改。正是因为如此,插件的同名方法会比视图的方法多一个参数(用于接收上一个方法传来的返回值)。但这不是绝对的。如果被hook的方法没有返回值则插件方法可以不用多设一个参数。
例如,我们想给ListAdminView传给模板的context中增加一个变量(var),我们可以这样定义一个插件:
以下是插件机制实现的原理,其实就是wrap 目标方法,在装饰器中遍历插件形成针对目标方法的插件方法列表,然后在目标方法执行后递归执行。
注意:比较巧妙的是,func if fargs[1] == '__' else func(),也就是说可以根据参数名来决定是把上一结果传过来还是把上一方法传过来,如果是把上一方法传过来
则可以控制方法的执行顺序,可以在上一方法执行前做点改动。
def filter_chain(filters, token, func, *args, **kwargs):
if token == -1:
return func()
else:
def _inner_method():
fm = filters[token]
fargs = getargspec(fm)[0]
if len(fargs) == 1:
# Only self arg
result = func()
if result is None:
return fm()
else:
raise IncorrectPluginArg(u'Plugin filter method need a arg to receive parent method result.')
else:
return fm(func if fargs[1] == '__' else func(), *args, **kwargs)
return filter_chain(filters, token - 1, _inner_method, *args, **kwargs) def filter_hook(func):
tag = func.__name__
func.__doc__ = "``filter_hook``\n\n" + (func.__doc__ or "") @functools.wraps(func)
def method(self, *args, **kwargs): def _inner_method():
return func(self, *args, **kwargs) if self.plugins:
filters = [(getattr(getattr(p, tag), 'priority', 10), getattr(p, tag))
for p in self.plugins if callable(getattr(p, tag, None))]
filters = [f for p, f in sorted(filters, key=lambda x:x[0])]
return filter_chain(filters, len(filters) - 1, _inner_method, *args, **kwargs)
else:
return _inner_method()
return method
xadmin的插件机制的更多相关文章
- 【学】jQuery的源码思路6——增加each,animaion,ajax以及插件机制
each() 插件机制 animation ajax //each() //这里第一个参数指定将this指向每次循环到的那个元素身上,而第三个参数element其实就是this本身所以和第一个参数是一 ...
- ImitateLogin新增插件机制以及又一个社交网站的支持
我的文章里已经多次介绍 imitate-login ,这是我最近一直在维护的一个使用c#模拟社交网站登录的开源项目,现在新增了对插件的支持以及一个新的网站(由于某种原因,会在文章结束部分介绍:而且仅会 ...
- Maven生命周期和插件机制
Maven中的一个非常重要的概念是生命周期和插件,这篇文章重点介绍下Maven的生命周期. Maven的生命周期是抽象的,具体的功能是有具体的插件来完成的,Maven有相当多的功能插件,以至于Mave ...
- php中的钩子(hook插件机制)
对"钩子"这个概念其实不熟悉,最近看到一个php框架中用到这种机制来扩展项目,所以大概来了解下. hook插件机制的基本思想: 在项目代码中,你认为要扩展(暂时不扩展)的地方放置一 ...
- winform插件机制学习
这两天在看自定义控件,原来有太多知识没有掌握.今天看到插件机制,心里突然一亮,这个东西听了不少次,就是不知道是啥回事.这次有幸书里包含一个案例,我就跟着它一步步来.终于知道是什么回事了.这个应该在软件 ...
- [转]仿World Wind构造自己的C#版插件框架——WW插件机制精简改造
很久没自己写东西啦,早该好好总结一下啦!一个大师说过“一个问题不应该被解决两次!”,除了一个好脑筋,再就是要坚持总结. 最近需要搞个系统的插件式框架,我参照World Wind的插件方式构建了个插件框 ...
- WordPress 插件机制的简单用法和原理(Hook 钩子)
WordPress 的插件机制实际上只的就是这个 Hook 了,它中文被翻译成钩子,允许你参与 WordPress 核心的运行,是一个非常棒的东西,下面我们来详细了解一下它. PS:本文只是简单的总结 ...
- 微信开发学习日记(八):7步看懂weiphp插件机制,核心目标是响应微信请求
又经过了几个小时的梳理.回顾,截至目前,终于对weiphp这个框架的机制搞明白了些.想要完全明白,自然还需要大把的时间.第1步: 配置微信公众号,http://weiphp.jiutianniao ...
- typecho流程原理和插件机制浅析(第二弹)
typecho流程原理和插件机制浅析(第二弹) 兜兜 393 2014年04月02日 发布 推荐 1 推荐 收藏 14 收藏,3.7k 浏览 上一次说了 Typecho 大致的流程,今天简单说一下插件 ...
随机推荐
- nginx配置中文域名解析
当nginx配置文件中的default如果遇到解析指向问题的时候 ,配置了中文 没有用 后来找了找这个网址 http://tools.jb51.net/punycode/ 然后进去转换了一下 把 评估 ...
- having的用法以及与where区别介绍
having子句可以让我们筛选成组后的各种数据,having子句在查询过程中慢于聚合语句,接下来通过实例介绍下,感兴趣的你可以参考下,希望可以帮助到你 having的用法 having子句可以让我们筛 ...
- [C#] 常用工具类——应用程序属性信息访问类
using System; using System.Collections.Generic; using System.Text; using System.Reflection; namespac ...
- LVM物理卷命令
1. 物理卷命令 一般维护命令: #pvscan //在系统的全部磁盘中搜索已存在的物理卷 #pvdisplay 物理卷全路径名称 //用于显示指定物理卷的属性. #pvdata 物理卷全路径名 ...
- 应用Druid监控SQL语句的执行情况--转载
Druid是什么? Druid首先是一个数据库连接池.Druid是目前最好的数据库连接池,在功能.性能.扩展性方面,都超过其他数据库连接池,包括DBCP.C3P0.BoneCP.Proxool.JBo ...
- ASP.NET获取汉字首字母
/// <summary> /// 获取汉字首字母(可包含多个汉字) /// </summary> /// <param name="strText" ...
- Spring文件上传出错:java.lang.ClassCastException: org.apache.catalina.connector.Request
java.lang.ClassCastException: org.apache.catalina.connector.RequestFacade cannot be cast to org.spri ...
- Razor的理解
[原创]Razor非常智能非常实用,不了解的人可能会觉得有没有都无所谓,其实不然,起初对Razor不是太了解,现在想想Razor就是来标示出C#语法的,但是HTML和C#混合输出时到底@这个小老鼠到底 ...
- php 计算一个字符串在另一个字符串中出现的次数
<?php $text = 'This is a test'; echo strlen($text); // 14 echo substr_count($text, 'is'); // 2 // ...
- Java 输入
1.使用Scanner 使用时需要引入包import java.util.Scanner;首先定义Scanner对象 Scanner sc = new Scanner(System.in);如果要输入 ...