如何更改 Django 管理过滤器以使用下拉列表而不是列表?

发布于 2024-10-26 08:36:54 字数 138 浏览 4 评论 0原文

如果您想要作为过滤依据的字段有超过 10 个值,则过滤侧边栏就会开始变得丑陋且难以使用。

我正在寻找一种解决方案,将

  • 替换为下拉选择(组合框)或类似的内容,以解决相同的问题。
  • If, for a field that you want to filter by, you have more than ~10 values, the filtering sidebar starts to be ugly and harder to use.

    I'm looking for a solution to replace the <li> with a dropdown selection (combobox) or something similar that will solve the same problem.

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

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

    发布评论

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

    评论(11

    葮薆情 2024-11-02 08:36:55

    我并不喜欢迄今为止提供的所有解决方案。

    为什么?如果您要筛选的字段有超过 10 个值,则列表视图框也不太方便。我建议使用 django admin 的标准搜索字段功能,它将显示一个搜索字段:

    class BooksAdmin(admin.ModelAdmin):
        list_display = ('ISBN', 'title')         
        search_fields = ('ISBN',)
        # instead of: list_filter = ('ISBN',)
        ordering = ('title',)  
    

    I am not a fan of all solutions provided up to now.

    Why? If, for a field that you want to filter by, you have more than 10 values, a listview box isn't that handy, too. I advice to use the standard search field capability of django admin which will show you a search field:

    class BooksAdmin(admin.ModelAdmin):
        list_display = ('ISBN', 'title')         
        search_fields = ('ISBN',)
        # instead of: list_filter = ('ISBN',)
        ordering = ('title',)  
    
    偏爱你一生 2024-11-02 08:36:55

    http://djangosuit.com/ 还提供列表过滤器的下拉菜单。

    http://djangosuit.com/ also offers dropdowns for list filters.

    老子叫无熙 2024-11-02 08:36:55

    最好的解决方案是在 admin/filter.html 中创建一个新模板并实现 @beholderrk 建议的 HTML 代码。刚刚为客户实现了它,效果很好。

    DropdownFilter 和RelatedDropdownFilter 的问题是它失去了正确的显示。它将显示 TrueFalse 等,而不是 Charfield(choices=xxx) 的翻译字符串。

    The best solution is to create a new template in admin/filter.html and implement the HTML code suggested by @beholderrk. Just implemented it for a client and it works great.

    Problem with DropdownFilter and RelatedDropdownFilter is that it loses the proper display. Instead of the translated strings for Charfield(choices=xxx), it will show True, False and so on.

    梦幻的味道 2024-11-02 08:36:55

    您能给出一个完整的例子吗?它显示像以前一样。
    这是我的代码

    from django.contrib import admin
    from pages.models import Post, Device, DeviceType, DeviceModel, Ipaddress, DeviceGroup, Location,Department,Comment
    from django_admin_listfilter_dropdown.filters import DropdownFilter, RelatedDropdownFilter
    
    
    class CommentInline(admin.TabularInline):
        model = Comment
    
    class IpaddressAdmin(admin.ModelAdmin):
            prepopulated_fields = {'slug': ('ipaddress',)}
    #        model=Ipaddress
    
            search_fields = ['ipaddress', ]
    #     
            list_display = ('ipaddress', 'machinename', 'user', 'department','location',)
            list_filter = (
            ('user', DropdownFilter),
            ('department', RelatedDropdownFilter),
            ('location', RelatedDropdownFilter),
    
        )
    

    这是屏幕截图在此处输入图像描述

    Could you please give a complete example. it shows like before.
    here is my code

    from django.contrib import admin
    from pages.models import Post, Device, DeviceType, DeviceModel, Ipaddress, DeviceGroup, Location,Department,Comment
    from django_admin_listfilter_dropdown.filters import DropdownFilter, RelatedDropdownFilter
    
    
    class CommentInline(admin.TabularInline):
        model = Comment
    
    class IpaddressAdmin(admin.ModelAdmin):
            prepopulated_fields = {'slug': ('ipaddress',)}
    #        model=Ipaddress
    
            search_fields = ['ipaddress', ]
    #     
            list_display = ('ipaddress', 'machinename', 'user', 'department','location',)
            list_filter = (
            ('user', DropdownFilter),
            ('department', RelatedDropdownFilter),
            ('location', RelatedDropdownFilter),
    
        )
    

    Here is the screenshotenter image description here

    失而复得 2024-11-02 08:36:55

    几周前我也遇到了同样的问题。所以这个答案可能对未来的一些开发人员有用。

    我设法通过编写自定义 template.html

    解决了该问题
    我现在已将代码捆绑在一个令人惊叹的包中,它对您也有同样的作用,这里是链接


    以下是如何实现可搜索下拉列表来代替默认列表:

    1.安装:

    pip install django-admin-searchable-dropdown
    

    此命令将在您的项目中安装最新版本的软件包。
    现在,通过将 admin_searchable_dropdown 添加到 settings.py 文件内的 INSTALLED_APPS 中,将该包包含在您的项目中。

    2.用法:
    假设您有以下型号:

    from django.db import models
    
    class CarCompany(models.Model):
        name = models.CharField(max_length=128)
    
    class CarModel(models.Model):
        name = models.CharField(max_length=64)
        company = models.ForeignKey(CarCompany, on_delete=models.CASCADE)
    

    并且您希望根据 company 过滤 CarModelAdmin 中的结果。您需要在 CarCompany 中定义 search_fields,然后定义如下过滤器:

    from django.contrib import admin
    from admin_searchable_dropdown.filters import AutocompleteFilter
    
    
    class CarCompanyFilter(AutocompleteFilter):
        title = 'Company' # display title
        field_name = 'company' # name of the foreign key field
    
    
    class CarCompanyAdmin(admin.ModelAdmin):
        search_fields = ['name'] # this is required for django's autocomplete functionality
        # ...
    
    
    class CarModelAdmin(admin.ModelAdmin):
        list_filter = [CarCompanyFilter]
        # ...
    

    按照这些步骤操作后,您可能会看到过滤器为:

    1. 这就是当使用包
    2. 下拉过滤器是还可搜索

    提供的功能:

    1. 如果您在管理过滤器中有较大的字段,则侧边栏会变宽,此软件包以下拉格式为您提供相同的列表,因此,没有这样的麻烦。
    2. 如果您有超过 20 个字段项目,列表过滤器现在是一个长侧窗格,只会破坏管理界面。下拉过滤器解决了这个问题。
    3. Dropdown 也是“可搜索的”,带有一个输入文本字段(利用 Django 自己的 auto_complete 功能),因此只要您使用的 Django 版本大于 2.0,就应该没问题。
    4. 您可以自定义您可能拥有的其他 list_filters,例如更改下拉列表上方的标题或自定义搜索逻辑等。
    5. 您可以自定义要在下拉选项中显示的小部件文本,以使用默认值以外的内容 <代码>str(obj)

    I was struggling with the same problem some few weeks back. So this answer might be useful to some developers from the future.

    I managed to solve the problem by writing a custom template.html

    I have bundled the code in an amazing package now that does the same for you, here's the link.


    Here's how you can implement a Searchable Dropdown in place of the default List:

    1. Installation:

    pip install django-admin-searchable-dropdown
    

    This command will install the latest version of the package in your project.
    Now, include the package in your project by adding admin_searchable_dropdown to your INSTALLED_APPS inside settings.py file.

    2. Usage:
    Let's say you have following models:

    from django.db import models
    
    class CarCompany(models.Model):
        name = models.CharField(max_length=128)
    
    class CarModel(models.Model):
        name = models.CharField(max_length=64)
        company = models.ForeignKey(CarCompany, on_delete=models.CASCADE)
    

    And you would like to filter results in CarModelAdmin on the basis of company. You need to define search_fields in CarCompany and then define filter like this:

    from django.contrib import admin
    from admin_searchable_dropdown.filters import AutocompleteFilter
    
    
    class CarCompanyFilter(AutocompleteFilter):
        title = 'Company' # display title
        field_name = 'company' # name of the foreign key field
    
    
    class CarCompanyAdmin(admin.ModelAdmin):
        search_fields = ['name'] # this is required for django's autocomplete functionality
        # ...
    
    
    class CarModelAdmin(admin.ModelAdmin):
        list_filter = [CarCompanyFilter]
        # ...
    

    After following these steps you may see the filter as:

    1. This is how the list filter is rendered in the form of a dropdown when the package is used
    2. And the dropdown filter is also Searchable

    Features Offered:

    1. If you have large fields in Admin Filter, the sidebar gets widened, this package provides you the same list in a dropdown format, hence, no such hassle.
    2. If you have more than, say 20, field items, list filter is now a long side-pane, just ruining the admin interface. The Dropdown filter fixes that.
    3. The Dropdown is also "Searchable", with an input text field (which utilizes Django's own auto_complete functionailty), so as long as the Django version you are using is greater than 2.0, you should be fine.
    4. You can customize other list_filters you may have, like change the Title above the dropdown, or a custom Search logic etc.
    5. You can customize Widget Texts to display in the Dropdown Option to use something other than the default str(obj)
    三生一梦 2024-11-02 08:36:55

    要向 @beholderrk 和 @Gediminas 解决方案添加搜索功能,请使用以下命令

    templates/admin 文件夹中创建 searchable_dropdown_filter.html 并将以下代码粘贴

    {% load i18n %}
    {% load static %}
    
    <!-- Django's Select2 CSS -->
    <link rel="stylesheet" type="text/css" href="{% static 'admin/css/vendor/select2/select2.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static 'admin/css/autocomplete.css' %}">
    
    <!-- jQuery (Django Admin uses this, so you can refer to it) -->
    <script src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>
    
    <!-- Django's Select2 JS -->
    <script src="{% static 'admin/js/vendor/select2/select2.full.js' %}"></script>
    
    <script type="text/javascript">
        $(document).ready(function() {
            $('.searchable-select').select2();
        });
    
        var go_from_select = function(opt) { window.location = window.location.pathname + opt };
    </script>
    
    
    <h3>{{ title }}</h3>
    <ul class="admin-filter-{{ title|cut:' ' }}">
    {% if choices|slice:"4:" %}
        <li>
        <select style="width: 95%;"
            onchange="go_from_select(this.options[this.selectedIndex].value)"
            class="searchable-select"
        >
        {% for choice in choices %}
            <option{% if choice.selected %} selected="selected"{% endif %}
             value="{{ choice.query_string|iriencode }}">{{ choice.display }}</option>
        {% endfor %}
        </select>
        </li>
    {% else %}
    
        {% for choice in choices %}
                <li{% if choice.selected %} class="selected"{% endif %}>
                <a href="{{ choice.query_string|iriencode }}">{{ choice.display }}</a></li>
        {% endfor %}
    
    {% endif %}
    </ul>
    
    

    admin.py 中filters.py 粘贴以下内容

    from django.contrib.admin.filters import RelatedFieldListFilter
    
    class SearchableDropdownFilter(RelatedFieldListFilter):
        template = 'admin/searchable_dropdown_filter.html'
    

    在您的管理实现中按如下方式使用它

    class SomeAdmin(admin.ModelAdmin):
        # ...
        list_filter = (('country', SearchableDropdownFilter), ('city', SearchableDropdownFilter),)
    

    这使用 select2 将搜索功能添加到下拉列表中。当您有大量要从中过滤的选项时,这非常方便。

    To add search functionality to @beholderrk and @Gediminas solution use the follow

    Create searchable_dropdown_filter.html in templates/admin folder and paste the following code

    {% load i18n %}
    {% load static %}
    
    <!-- Django's Select2 CSS -->
    <link rel="stylesheet" type="text/css" href="{% static 'admin/css/vendor/select2/select2.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static 'admin/css/autocomplete.css' %}">
    
    <!-- jQuery (Django Admin uses this, so you can refer to it) -->
    <script src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>
    
    <!-- Django's Select2 JS -->
    <script src="{% static 'admin/js/vendor/select2/select2.full.js' %}"></script>
    
    <script type="text/javascript">
        $(document).ready(function() {
            $('.searchable-select').select2();
        });
    
        var go_from_select = function(opt) { window.location = window.location.pathname + opt };
    </script>
    
    
    <h3>{{ title }}</h3>
    <ul class="admin-filter-{{ title|cut:' ' }}">
    {% if choices|slice:"4:" %}
        <li>
        <select style="width: 95%;"
            onchange="go_from_select(this.options[this.selectedIndex].value)"
            class="searchable-select"
        >
        {% for choice in choices %}
            <option{% if choice.selected %} selected="selected"{% endif %}
             value="{{ choice.query_string|iriencode }}">{{ choice.display }}</option>
        {% endfor %}
        </select>
        </li>
    {% else %}
    
        {% for choice in choices %}
                <li{% if choice.selected %} class="selected"{% endif %}>
                <a href="{{ choice.query_string|iriencode }}">{{ choice.display }}</a></li>
        {% endfor %}
    
    {% endif %}
    </ul>
    
    

    In your admin.py or filters.py paste the following

    from django.contrib.admin.filters import RelatedFieldListFilter
    
    class SearchableDropdownFilter(RelatedFieldListFilter):
        template = 'admin/searchable_dropdown_filter.html'
    

    In your admin implementation use it as follows

    class SomeAdmin(admin.ModelAdmin):
        # ...
        list_filter = (('country', SearchableDropdownFilter), ('city', SearchableDropdownFilter),)
    

    This uses select2 to add search functionality to the dropdown. This is very handy when you have a ton of options you want to filter from.

    迟月 2024-11-02 08:36:54

    谢谢@beholderrk、@gediminas 和@jk-laiho!我将其打包到可重用应用中。

    安装:

    pip install django-admin-list-filter-dropdown
    

    settings.py 中启用:

    INSTALLED_APPS = (
        ...
        'django_admin_listfilter_dropdown',
        ...
    )
    

    admin.py 中使用:

    from django_admin_listfilter_dropdown.filters import (
        DropdownFilter, ChoiceDropdownFilter, RelatedDropdownFilter
    )
    
    class EntityAdmin(admin.ModelAdmin):
        ...
        list_filter = (
            # for ordinary fields
            ('a_charfield', DropdownFilter),
            # for choice fields
            ('a_choicefield', ChoiceDropdownFilter),
            # for related fields
            ('a_foreignkey_field', RelatedDropdownFilter),
        )
    

    如下所示:

    下拉列表过滤器的屏幕截图

    Thanks @beholderrk, @gediminas and @jk-laiho! I packaged this into a reusable app.

    Install:

    pip install django-admin-list-filter-dropdown
    

    Enable in settings.py:

    INSTALLED_APPS = (
        ...
        'django_admin_listfilter_dropdown',
        ...
    )
    

    Use in admin.py:

    from django_admin_listfilter_dropdown.filters import (
        DropdownFilter, ChoiceDropdownFilter, RelatedDropdownFilter
    )
    
    class EntityAdmin(admin.ModelAdmin):
        ...
        list_filter = (
            # for ordinary fields
            ('a_charfield', DropdownFilter),
            # for choice fields
            ('a_choicefield', ChoiceDropdownFilter),
            # for related fields
            ('a_foreignkey_field', RelatedDropdownFilter),
        )
    

    Here's what it looks like:

    Screenshot of dropdown list filter

    巴黎夜雨 2024-11-02 08:36:54

    我无法评论答案,因此我将在这里添加到 beholderrk 的答案中。

    1. 创建一个名为 dropdown_filter.html 的新模板,或类似的
    2. 将 filter.html 的代码从 feincms 复制到 dropdown_filter.html
    3. filters 中创建一个新的过滤器类.py

      from django.contrib.admin.filters import AllValuesFieldListFilter
      
      类 DropdownFilter(AllValuesFieldListFilter):
          模板 = 'admin/dropdown_filter.html'
      
    4. 现在您可以在管理类中使用此过滤器:

      类 SomeAdmin(admin.ModelAdmin):
          # ...
          list_filter = (('国家', DropdownFilter),)
      

    效果很好!

    I cannot comment answers so I'll add to beholderrk's answer here.

    1. create a new template called dropdown_filter.html or similar
    2. copy the code of filter.html from feincms to dropdown_filter.html
    3. create a new filter class in filters.py:

      from django.contrib.admin.filters import AllValuesFieldListFilter
      
      class DropdownFilter(AllValuesFieldListFilter):
          template = 'admin/dropdown_filter.html'
      
    4. now you can use this filter in your admin class:

      class SomeAdmin(admin.ModelAdmin):
          # ...
          list_filter = (('country', DropdownFilter),)
      

    Works great!

    奢欲 2024-11-02 08:36:54

    使用 feincms 中的 filter.html

    {% load i18n %}
    <script type="text/javascript">var go_from_select = function(opt) { window.location = window.location.pathname + opt };</script>
    <h3>{{ title }}</h3>
    <ul class="admin-filter-{{ title|cut:' ' }}">
    {% if choices|slice:"4:" %}
        <li>
        <select style="width: 95%;"
            onchange="go_from_select(this.options[this.selectedIndex].value)">
        {% for choice in choices %}
            <option{% if choice.selected %} selected="selected"{% endif %}
             value="{{ choice.query_string|iriencode }}">{{ choice.display }}</option>
        {% endfor %}
        </select>
        </li>
    {% else %}
    
        {% for choice in choices %}
                <li{% if choice.selected %} class="selected"{% endif %}>
                <a href="{{ choice.query_string|iriencode }}">{{ choice.display }}</a></li>
        {% endfor %}
    
    {% endif %}
    </ul>
    

    Use filter.html from feincms

    {% load i18n %}
    <script type="text/javascript">var go_from_select = function(opt) { window.location = window.location.pathname + opt };</script>
    <h3>{{ title }}</h3>
    <ul class="admin-filter-{{ title|cut:' ' }}">
    {% if choices|slice:"4:" %}
        <li>
        <select style="width: 95%;"
            onchange="go_from_select(this.options[this.selectedIndex].value)">
        {% for choice in choices %}
            <option{% if choice.selected %} selected="selected"{% endif %}
             value="{{ choice.query_string|iriencode }}">{{ choice.display }}</option>
        {% endfor %}
        </select>
        </li>
    {% else %}
    
        {% for choice in choices %}
                <li{% if choice.selected %} class="selected"{% endif %}>
                <a href="{{ choice.query_string|iriencode }}">{{ choice.display }}</a></li>
        {% endfor %}
    
    {% endif %}
    </ul>
    
    2024-11-02 08:36:54

    一个简单的选择是使用 django-grappelli,它将所有过滤器替换为下拉列表。

    An easy option would be to use django-grappelli, which replaces all the filters with drop downs.

    或十年 2024-11-02 08:36:54

    您可以将管理模板从 django 安装复制到项目中的 templates/admin 文件夹中。

    然后,您需要在要在其中显示输出的表单或模板中执行以下两件事中的任意一项:

    1. 如果您正在使用表单,则您希望将列表选项发布回数据库,你会在你的 model.py 中,在你有选择的字段中,输入如下内容:

      choice = forms.IntegerField(widget=forms.Select(choices=CHOICES))
      
    2. 如果只是为了在页面上显示,那么你将在模板标签上输出这样的内容:

      <前><代码><选择>;
      {% for options in object.details.all %}
      <选项> {{ object.choice }}
      {% 结束 %}

    You can copy the admin templates from the django installation into you templates/admin folder in your project.

    Then you will need to do any of 2 things in the forms or templates you want to show your outputs in:

    1. If you are working with a form, in that you would like the list choices to be posted back to a database, you would in your model.py, on the field you have your choices, put in some this like this:

      choice = forms.IntegerField(widget=forms.Select(choices=CHOICES))
      
    2. If it is just to display on a page, then you will output on a template tag something like this:

      <select>
        {% for choices in object.details.all %}
          <option> {{ object.choice }} </option>
        {% endfor %}
      </select>
      
    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文