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的插件机制的更多相关文章

  1. 【学】jQuery的源码思路6——增加each,animaion,ajax以及插件机制

    each() 插件机制 animation ajax //each() //这里第一个参数指定将this指向每次循环到的那个元素身上,而第三个参数element其实就是this本身所以和第一个参数是一 ...

  2. ImitateLogin新增插件机制以及又一个社交网站的支持

    我的文章里已经多次介绍 imitate-login ,这是我最近一直在维护的一个使用c#模拟社交网站登录的开源项目,现在新增了对插件的支持以及一个新的网站(由于某种原因,会在文章结束部分介绍:而且仅会 ...

  3. Maven生命周期和插件机制

    Maven中的一个非常重要的概念是生命周期和插件,这篇文章重点介绍下Maven的生命周期. Maven的生命周期是抽象的,具体的功能是有具体的插件来完成的,Maven有相当多的功能插件,以至于Mave ...

  4. php中的钩子(hook插件机制)

    对"钩子"这个概念其实不熟悉,最近看到一个php框架中用到这种机制来扩展项目,所以大概来了解下. hook插件机制的基本思想: 在项目代码中,你认为要扩展(暂时不扩展)的地方放置一 ...

  5. winform插件机制学习

    这两天在看自定义控件,原来有太多知识没有掌握.今天看到插件机制,心里突然一亮,这个东西听了不少次,就是不知道是啥回事.这次有幸书里包含一个案例,我就跟着它一步步来.终于知道是什么回事了.这个应该在软件 ...

  6. [转]仿World Wind构造自己的C#版插件框架——WW插件机制精简改造

    很久没自己写东西啦,早该好好总结一下啦!一个大师说过“一个问题不应该被解决两次!”,除了一个好脑筋,再就是要坚持总结. 最近需要搞个系统的插件式框架,我参照World Wind的插件方式构建了个插件框 ...

  7. WordPress 插件机制的简单用法和原理(Hook 钩子)

    WordPress 的插件机制实际上只的就是这个 Hook 了,它中文被翻译成钩子,允许你参与 WordPress 核心的运行,是一个非常棒的东西,下面我们来详细了解一下它. PS:本文只是简单的总结 ...

  8. 微信开发学习日记(八):7步看懂weiphp插件机制,核心目标是响应微信请求

    又经过了几个小时的梳理.回顾,截至目前,终于对weiphp这个框架的机制搞明白了些.想要完全明白,自然还需要大把的时间.第1步:   配置微信公众号,http://weiphp.jiutianniao ...

  9. typecho流程原理和插件机制浅析(第二弹)

    typecho流程原理和插件机制浅析(第二弹) 兜兜 393 2014年04月02日 发布 推荐 1 推荐 收藏 14 收藏,3.7k 浏览 上一次说了 Typecho 大致的流程,今天简单说一下插件 ...

随机推荐

  1. ASP.NET MVC- Controllers and Routing- Routing

    二.Creating Custom Routes In this tutorial, you learn how to  add a custom route to an ASP.NET MVC ap ...

  2. [转]mysql 5.6 存储过程+事务+游标+错误异常抛出+日志写入

    转自:http://www.wolonge.com/post/detail/118249 DELIMITER $$ USE `ecstore`$$ DROP PROCEDURE IF EXISTS ` ...

  3. gwt中java与js的相互调用

    1. java通过jsni调用内部js Button button = new Button("java调用内部jsni的js方法"); button.addClickHandle ...

  4. asp.net mvc 两级分类联动方法示例

    前台视图代码 <%:Html.DropDownList("AwardClassMainID","请选择")%> <%:Html.DropDow ...

  5. 色情不是我的所有——在法律边缘起舞的 FC2

    [核心提示] 世界上最大的色情站点之中的一个这项「殊荣」只是是 FC2 无心插柳被用户戴上的一顶帽子,这个从 1999 年成立至今已经超过 15 年历史的互联网活化石,远比你想象中更加高深莫測. 一个 ...

  6. Rsync同步工具安装文档

    (1)下载Rsync源代码进行安装 (2)1'   cd rsync 2'   ./configure   --prefix=/usr/local/rsync 3'   make 4'   make  ...

  7. Android网络:HTTP之利用HttpURLConnection访问网页、获取网络图片实例 (附源码)

    http://blog.csdn.net/yanzi1225627/article/details/22222735 如前文所示的TCP局域网传送东西,除了对传输层的TCP/UDP支持良好外,Andr ...

  8. 偷偷mark下一个

    java书单 thinking in java java战 Effective Java 深入了解JVM虚拟机 java性能优化权威指南 JSR133 Google Guava官方教程 版权声明:本文 ...

  9. session的固化(搁置)

    Session在其生命周期中,可能会在运行时状态和持久化状态之间转换. 会话从运行时状态变为持久化状态的过程称为 -- 搁置:在以下情况下,Session会被搁置: 当服务器总之或单个Web应用终止时 ...

  10. GUI编程笔记(java)04:GUI(HelloWorld)窗体案例

    1.Frame 在JAVA中,Frame是一种控件,可作为父窗体加载其他swing控件.案例: package cn.itcast_01; import java.awt.Frame; public ...