zoukankan      html  css  js  c++  java
  • django xadmin 插件(2) 列表视图新增一功能列

    以默认的related_link为例(即最后一列)。

    源码:xadmin.plugins.relate.RelatedMenuPlugin  

    class RelateMenuPlugin(BaseAdminPlugin):
    
        use_related_menu = True
    
        # ...若干删减
    
        def related_link(self, instance):
            #... 若干删减
            return '<div class="dropdown related_menu pull-right"><a title="%s" class="relate_menu dropdown-toggle" data-toggle="dropdown"><i class="icon fa fa-list"></i></a>%s</div>' % (_('Related Objects'), ul_html)
    
        related_link.short_description = '&nbsp;'
        related_link.allow_tags = True
        related_link.allow_export = False
        related_link.is_column = False
    
        def get_list_display(self, list_display):
            if self.use_related_menu and len(self.get_related_list()):
                list_display.append('related_link')
                self.admin_view.related_link = self.related_link
            return list_display

    注解:

    1. 重写了ListAdminView的get_list_display方法(控制哪些字段加载)。

    2. 此处增加的字段是实际数据模型不存在的字段,否则无效。详细看xadmin.util中的lookup_field方法(需要触发字段不存在的异常,进入对应名称的同名方法调用并采用其返回值),源码如下:

    def lookup_field(name, obj, model_admin=None):
        opts = obj._meta
        try:
            f = opts.get_field(name)
        except models.FieldDoesNotExist:
            # For non-field values, the value is either a method, property or
            # returned via a callable.
            if callable(name):
                attr = name
                value = attr(obj)
            elif (model_admin is not None and hasattr(model_admin, name) and
                  not name == '__str__' and not name == '__unicode__'):
                attr = getattr(model_admin, name)
                value = attr(obj)
            else:
                attr = getattr(obj, name)
                if callable(attr):
                    value = attr()
                else:
                    value = attr
            f = None
        else:
            attr = None
            value = getattr(obj, name)
        return f, attr, value

    3. 字段的渲染逻辑需要自行实现,此处是 related_link方法, 最终返回html代码。

    4. 自定义字段的html代码能正常解析,不被和谐,不许要设置方法的allow_tags属性。

    related_link.allow_tags = True

    5. 栏位的名称,通过方法的short_description控制。

    related_link.short_description = '&nbsp;'

    6. (待分析)很神奇的,该插件没有init_request方法,却能通过 use_related_menu属性控制插件是否加载。

    新增字段默认返回html代码,要想其不被和谐, 方法的allow_tags属性需要为True,如下

    related_link.allow_tags = True 
    

      ---后记---------

          后来分析了下源码:xadmin/views/base.py (BaseAdminView类的init_plugin方法: 276行)

    def init_plugin(self, *args, **kwargs):
            plugins = []
            for p in self.base_plugins:
                p.request = self.request
                p.user = self.user
                p.args = self.args
                p.kwargs = self.kwargs
                import pdb
                pdb.set_trace()
                result = p.init_request(*args, **kwargs)
                if result is not False:
                    plugins.append(p)
            self.plugins = plugins

     默认情况下, 父类(BaseAdminPlugin)的init_request 不返回任何值,即为None, None is not False, 因此,没有init_request方法的自定义插件默认加载。之所以貌似能够用use_related_menu属性来控制“加载”与否,纯粹因为实际逻辑是:

      1. 默认加载控件 

          2. 如果use_related_menu为True,则渲染相关列菜单。否则啥都不做。

      代码如下:xadmin/plugins/relate.py (79~83)

    def get_list_display(self, list_display):
            if self.use_related_menu and len(self.get_related_list()):
                list_display.append('related_link')
                self.admin_view.related_link = self.related_link
            return list_display

        

    最终效果,就是在列表后追加了一列,如下:

    转载请注明来源:http://www.cnblogs.com/Tommy-Yu/p/5417987.html

    谢谢!

  • 相关阅读:
    编程语言扮演的3个角色,它连接了机器、开发者以及团队!
    20行代码爬取王者荣耀全英雄皮肤!让你享受白嫖的快乐!
    3分钟教会你如何发布Qt程序!高级编程界面开发也是如此的简单!
    C 语言实现一个简单的 web 服务器!了解 Socket 通讯工作原理!
    log4j
    解决MySQL 一闪而过的情况
    subversion和客户端的应用
    Map集合
    代码块执行顺序。
    ArrayList-VS-LinkedList
  • 原文地址:https://www.cnblogs.com/Tommy-Yu/p/5417987.html
Copyright © 2011-2022 走看看