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

发布于 2024-11-08 18:43:20 字数 177 浏览 0 评论 0原文

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

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

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

I quite like the filter feature of django admin views (list_filter).

But, on views with a lot of fields, I would really like the ability to minimize/expand it with a click, to save screen real-estate and also because it sometimes actually hides stuff.

Is there an easy way to add a collapse button (some already existing plugin I haven't found or something similar)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

笔落惊风雨 2024-11-15 18:43:21

对此进行了另一项更改,以便当您单击顶部的 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);

Made another change to this so that the H3's are hidden, as well as the filter lists, when you click on the top H2. This will get the entire list of filters out of the way if you click on the top "Filters".

This is the js file content

;(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);
半窗疏影 2024-11-15 18:43:21

修改 fanlix 解决方案为:

  1. 将光标显示为悬停时的指针
  2. 默认折叠

代码

(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);

Modified fanlix solution to:

  1. Show cursor as pointer on hover
  2. Be folded by default

Code

(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);
残月升风 2024-11-15 18:43:21

结合了 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);

Combined Tim's and maGo's approaches, with some tweaks:

Pros:

  • Allows user to hide the entire list (added "click to hide/unhide" to the filter list title so user knows what to do).
  • Maintains folded filter categories by default

Cons:

  • The page refresh after a filter is selected causes the filter categories to fold once again; ideally the ones you're working with would stay open.

The code:

(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);
赠佳期 2024-11-15 18:43:21

我编写了菜单折叠和单元素菜单折叠的片段。

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

如果先前激活了过滤器,则与此相关的元素菜单将按打开状态启动。

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

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

I wrote a snippets for menu collapse and single element menu collapse.

It's a fork from abyx code, I've just extended it.

If a filter was previously activated the element menu related to this will start as opened.

The filter menu starts closed as default.
Hope this helps

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

顾铮苏瑾 2024-11-15 18:43:21

Giuseppe De Marco 的片段效果最好。所以我在这里添加他的代码片段以便于访问。它甚至解决了 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);

Giuseppe De Marco's snippet works best. So i am adding his code snippet here for easy access. It even solves the problem (Cons) discussed above by 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);

成熟稳重的好男人 2024-11-15 18:43:21

Django 4.x,这是我的做法。

  1. 创建管理模板如下

    {% extends "admin/change_list.html" %} {% 阻止额外样式 %}
    {{ 块.super }}

    函数toggle_filter() {
    $("#changelist-filter").toggle("慢");
    };

    $(文档).ready(函数(){
    // 默认关闭它们
    $("#changelist-filter").toggle("快速");
    }); {% 末端嵌段 %}

  2. 增强 admin/base_site.html 添加按钮

<button onclick="toggle_filter()" class="btn btn-warning btn-sm" type="submit">Toggle Filter</button>

Django 4.x, here is how I do.

  1. create admin template as below

    {% extends "admin/change_list.html" %} {% block extrastyle %}
    {{ block.super }}

    function toggle_filter() {
    $("#changelist-filter").toggle("slow");
    };

    $(document).ready(function(){
    // close them by default
    $("#changelist-filter").toggle("fast");
    }); {% endblock %}

  2. enhance admin/base_site.html to add button

<button onclick="toggle_filter()" class="btn btn-warning btn-sm" type="submit">Toggle Filter</button>

久而酒知 2024-11-15 18:43:21

由于某种原因,Javascript 无法与 Django 5 一起使用。
我最终用一些自定义 CSS 覆盖了模板,通过采用变更列表模板,效果很好。
您还可以正确地在媒体中仅添加自定义 CSS 文件。

{% extends "admin/change_list.html" %}

{% block header %}
    {{ block.super }}

    <style>

        /* make changelist filter small by default */
        #changelist-filter {
          position: absolute;
          display: block;
          right: 0;
          border: solid rgba(255, 0, 0, 0.2) 0.5px;
          width: 8em;
          height: 2em;
        }
        /* prevent inner elements to be visible */
        #changelist-filter * {
          height: 0;
          display: none;
        }
        /* but show the filter header */
        #changelist-filter-header {
          height: auto;
          display: block;
        }
        /* when hovering, recover size again */
        #changelist-filter:hover {
          height: auto;
          width: auto;
        }
        /* and display the inner content */
        #changelist-filter:hover * {
          height: auto;
          display: block;
        }

    </style>
{% endblock %}

无悬停视图:

无悬停视图

正常悬停视图:

悬停视图

For some reason the the Javascripts didn't work with Django 5.
I ended up overwriting the template with some custom CSS, which works just fine, by adopting the changelists template.
You could properly also add only a custom CSS file inside the media.

{% extends "admin/change_list.html" %}

{% block header %}
    {{ block.super }}

    <style>

        /* make changelist filter small by default */
        #changelist-filter {
          position: absolute;
          display: block;
          right: 0;
          border: solid rgba(255, 0, 0, 0.2) 0.5px;
          width: 8em;
          height: 2em;
        }
        /* prevent inner elements to be visible */
        #changelist-filter * {
          height: 0;
          display: none;
        }
        /* but show the filter header */
        #changelist-filter-header {
          height: auto;
          display: block;
        }
        /* when hovering, recover size again */
        #changelist-filter:hover {
          height: auto;
          width: auto;
        }
        /* and display the inner content */
        #changelist-filter:hover * {
          height: auto;
          display: block;
        }

    </style>
{% endblock %}

No hover view:

No Hover View

Hover view as normal:

Hover view

維他命╮ 2024-11-15 18:43:20

鉴于您现在在 django admin 中拥有 jQuery,可以轻松地将 slideToggle() 绑定到列表过滤器中的标题。

这似乎足以让它工作:

// 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 子类中,您想要激活设置媒体内部类:

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

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

Given that you now have jQuery in django admin, it's easy to bind a slideToggle() to the titles in the List Filter.

This seems enough Javascript for it to work:

// 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);

Then in the ModelAdmin subclass you want to activate that set the Media inner class:

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

Make sure to drop the list_filter_collapse.js file in a 'js' folder inside your STATIC_DIRS or STATIC_ROOT (Depending on your Django version)

简单气质女生网名 2024-11-15 18:43:20

我更改了 Jj 的答案,以在单击“过滤器”标题时折叠整个过滤器,为了完整性将其添加到此处,要点如下 这里

(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);

I changed Jj's answer to collapse the whole filter when clicking on the 'filter' title, adding it here for completeness, a gist is available 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);
羞稚 2024-11-15 18:43:20

为此,我编写了一个小片段,可在 bitbucket 上下载。

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

在此处输入图像描述

I have written a small snippets downloadable on bitbucket for the purpose.

The state of the filters are stored in a cookie and the selected filters stay visible.

enter image description here

暮色兮凉城 2024-11-15 18:43:20

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

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

这是 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);

Thanks to @JJ's idea.
I added toggles for the whole window, simpler than @abyx's implement.

  1. Toggle the whole filter by clicking "Filter" title
  2. Toggle each list by clicking list title

This is the js file content:

;(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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文