最小化 django-admin 中的列表过滤器

Posted

技术标签:

【中文标题】最小化 django-admin 中的列表过滤器【英文标题】:Minimize the list filter in django-admin 【发布时间】:2011-08-30 12:12:08 【问题描述】:

我很喜欢 django 管理视图的过滤功能 (list_filter)。

但是,对于具有很多字段的视图,我真的希望能够通过单击来最小化/扩展它,以节省屏幕空间,而且因为它有时实际上隐藏了一些东西。

有没有一种简单的方法来添加折叠按钮(一些我还没有找到的现有插件或类似的东西)?

【问题讨论】:

【参考方案1】:

鉴于您现在在 django admin 中拥有 jQuery,很容易将 slideToggle() 绑定到列表过滤器中的标题。

这似乎足以让 javascript 工作:

// Fancier version https://gist.github.com/985283 

;(function($) $(document).ready(function()
    $('#changelist-filter').children('h3').each(function()
        var $title = $(this);
        $title.click(function()
            $title.next().slideToggle();
        );
    );   
  );
)(django.jQuery);

然后在你要激活的ModelAdmin子类中设置Media内部类:

class MyModelAdmin(admin.ModelAdmin):
  list_filter = ['bla', 'bleh']
  class Media:
    js = ['js/list_filter_collapse.js']

确保将 list_filter_collapse.js 文件放在 STATIC_DIRS 或 STATIC_ROOT 内的“js”文件夹中(取决于您的 Django 版本)

【讨论】:

我希望在您单击“过滤器”部分时切换整个过滤器 嘿,这正是我要找的,但我不知道这段 javascript 代码应该去哪里。它应该放入哪些文件? @wobbily_col,Media 中的文件是相对于 STATIC 的。我所做的方法是创建一个“js/admin”目录,并使文件被加载“js/admin/list_filter_collapse.js”。【参考方案2】:

我更改了 Jj 的答案以在单击“过滤器”标题时折叠整个过滤器,为了完整起见,将其添加到此处,提供要点here:

(function($)
ListFilterCollapsePrototype = 
    bindToggle: function()
        var that = this;
        this.$filterTitle.click(function()
            that.$filterContent.slideToggle();
            that.$list.toggleClass('filtered');
        );
    ,
    init: function(filterEl) 
        this.$filterTitle = $(filterEl).children('h2');
        this.$filterContent = $(filterEl).children('h3, ul');
        $(this.$filterTitle).css('cursor', 'pointer');
        this.$list = $('#changelist');
        this.bindToggle();
    

function ListFilterCollapse(filterEl) 
    this.init(filterEl);

ListFilterCollapse.prototype = ListFilterCollapsePrototype;

$(document).ready(function()
    $('#changelist-filter').each(function()
        var collapser = new ListFilterCollapse(this);
    );
);
)(django.jQuery);

【讨论】:

谢谢,您的 js 代码在 Django 1.9.9 上比其他代码运行得更好。能不能让fitter list默认折叠?【参考方案3】:

为此,我写了一个可在bitbucket 上下载的小sn-ps。

过滤器的状态存储在 cookie 中,所选过滤器保持可见。

【讨论】:

【参考方案4】:

感谢@JJ 的想法。 我为整个窗口添加了切换,比 @abyx 的实现简单。

    通过单击“过滤器”标题切换整个过滤器 通过单击列表标题切换每个列表

这是js文件内容:

;(function($) $(document).ready(function()
    $('#changelist-filter > h3').each(function()
        var $title = $(this);
        $title.click(function()
            $title.next().slideToggle();
        ); 
    );   
    var toggle_flag = true;
    $('#changelist-filter > h2').click(function () 
        toggle_flag = ! toggle_flag;
        $('#changelist-filter > ul').each(function()
                $(this).toggle(toggle_flag);
        ); 
    );   
  ); 
)(django.jQuery);

【讨论】:

【参考方案5】:

对此进行了另一项更改,以便在您单击顶部 H2 时隐藏 H3 以及过滤器列表。如果您单击顶部的“过滤器”,这将清除整个过滤器列表。

这是js文件内容

;(function($) $(document).ready(function()
    $('#changelist-filter > h3').each(function()
        var $title = $(this);
        $title.click(function()
            $title.next().slideToggle();
        );
    );
    var toggle_flag = true;
    $('#changelist-filter > h2').click(function () 
        toggle_flag = ! toggle_flag;
        $('#changelist-filter').find('> ul, > h3').each(function()
                $(this).toggle(toggle_flag);
        );
    );
  );
)(django.jQuery);

【讨论】:

【参考方案6】:

修改 fanlix 解决方案为:

    在悬停时将光标显示为指针 默认折叠

代码

(function($) $(document).ready(function()
    $('#changelist-filter > h3').each(function()
        var $title = $(this);
        $title.next().toggle();
        $title.css("cursor","pointer");
        $title.click(function()
            $title.next().slideToggle();
        );
    );
    var toggle_flag = false;
    $('#changelist-filter > h2').css("cursor","pointer");
    $('#changelist-filter > h2').click(function () 
        toggle_flag = ! toggle_flag;
        $('#changelist-filter > ul').each(function()
            $(this).slideToggle(toggle_flag);
        );
    );
  ); 
)(django.jQuery);

【讨论】:

【参考方案7】:

结合了 Tim 和 maGo 的方法,并进行了一些调整:

优点:

允许用户隐藏整个列表(在过滤器列表标题中添加了“点击隐藏/取消隐藏”,以便用户知道该怎么做)。 默认维护折叠过滤器类别

缺点:

选择过滤器后的页面刷新导致过滤器类别再次折叠;理想情况下,与您合作的那些会保持开放。

代码:

(function($) $(document).ready(function()

    // Start with a filter list showing only its h3 subtitles; clicking on any
    // displays that filter's content; clicking again collapses the list:
    $('#changelist-filter > h3').each(function()
        var $title = $(this);
        $title.next().toggle();
        $title.css("cursor","pointer");
        $title.click(function()
            $title.next().slideToggle();
        );
    );

    // Add help after title:
    $('#changelist-filter > h2').append("<span style='font-size: 80%; color: grey;'> (click to hide/unhide)</span>");

    // Make title clickable to hide entire filter:
    var toggle_flag = true;
    $('#changelist-filter > h2').click(function () 
        toggle_flag = ! toggle_flag;
        $('#changelist-filter').find('> h3').each(function()
                $(this).toggle(toggle_flag);
        );
    );
  );
)(django.jQuery);

【讨论】:

【参考方案8】:

我为菜单折叠和单元素菜单折叠写了一个 sn-ps。

这是 abyx 代码的一个分支,我刚刚对其进行了扩展。

如果之前激活了过滤器,则与此相关的元素菜单将在打开时开始。

过滤器菜单默认关闭。 希望这会有所帮助

https://github.com/peppelinux/Django-snippets/tree/master/django-admin.js-snippets

【讨论】:

请将代码 sn-p 添加到您的答案中,不要只是链接到它。【参考方案9】:

Giuseppe De Marco 的 sn-p 效果最好。所以我在这里添加他的代码 sn-p 以便于访问。它甚至解决了上面 joelg 讨论的问题(缺点):

// Copied from 
// https://github.com/peppelinux/Django-snippets/tree/master/django-admin.js-snippets

(function($)
    
    var element_2_collapse = '#changelist-filter';
    var element_head       = 'h2'
    var filter_title       = 'h3'
    
    // this is needed for full table resize after filter menu collapse
    var change_list        = '#changelist'
    
    
    ListFilterCollapsePrototype = 
        bindToggle: function()
            var that = this;
            this.$filterTitle.click(function()
                
                // check if some ul is collapsed
                // open it before slidetoggle all together
                $(element_2_collapse).children('ul').each(function()
                    if($(this).is(":hidden"))
                        
                            $(this).slideToggle();
                                    
                )
                
                // and now slidetoggle all 
                that.$filterContentTitle.slideToggle();
                that.$filterContentElements.slideToggle();            
                that.$list.toggleClass('filtered');
    
            );
    
        ,
        init: function(filterEl) 
            this.$filterTitle = $(filterEl).children(element_head);
            this.$filterContentTitle = $(filterEl).children(filter_title);
            this.$filterContentElements = $(filterEl).children('ul');
            $(this.$filterTitle).css('cursor', 'pointer');
            this.$list = $(change_list );
            
            // header collapse
            this.bindToggle();
        
            // collapsable childrens 
            $(element_2_collapse).children(filter_title).each(function()
                var $title = $(this);
                $title.click(function()
                    $title.next().slideToggle();
                            
                );
            
            $title.css('border-bottom', '1px solid grey');
            $title.css('padding-bottom', '5px');
            $title.css('cursor', 'pointer');     
            
            );
        
        
            
        
    
    function ListFilterCollapse(filterEl) 
        this.init(filterEl);
    
    ListFilterCollapse.prototype = ListFilterCollapsePrototype;
    
    $(document).ready(function()
        $(element_2_collapse).each(function()
            var collapser = new ListFilterCollapse(this);
        );
        
        // close them by default
        $(element_2_collapse+' '+element_head).click()
        
        // if some filter was clicked it will be visible for first run only
        // selezione diverse da Default
        
    
        $(element_2_collapse).children(filter_title).each(function()
            
            lis = $(this).next().children('li')
            lis.each(function(cnt) 
              if (cnt > 0)
               
                if ($(this).hasClass('selected')) 
                    $(this).parent().slideDown(); 
                    $(this).parent().prev().slideDown();
                    
                    // if some filters is active every filters title (h3) 
                    // should be visible
                    $(element_2_collapse).children(filter_title).each(function()
                        $(this).slideDown(); 
                    )
                    
                    $(change_list).toggleClass('filtered');
                    
                
               
            )
    
        );
    
    );
    )(django.jQuery);

【讨论】:

以上是关于最小化 django-admin 中的列表过滤器的主要内容,如果未能解决你的问题,请参考以下文章

Django-admin:如何在记录更改列表中显示指向对象信息页面的链接而不是编辑表单?

django-admin的源码流程

django-admin 仿写stark组件action,filter筛选过滤,search查询

序言中列表列表中的最小值

通过javascript过滤复选框列表的最小代码

Django学习第29篇:django-admin的源码流程