【问题标题】:How to change the Django admin filter to use a dropdown instead of list?如何更改 Django 管理过滤器以使用下拉列表而不是列表?
【发布时间】:2011-07-22 16:55:15
【问题描述】:

如果对于您要过滤的字段,您有超过 10 个值,则过滤侧边栏开始变得丑陋且难以使用。

我正在寻找一种解决方案,将<li> 替换为下拉选择(组合框)或类似的东西来解决相同的问题。

【问题讨论】:

  • 你看过 django-grappelli 吗?看起来正是你想要的,所以你可以看看它是如何完成的。

标签: django django-admin


【解决方案1】:

几周前我也在为同样的问题苦苦挣扎。所以这个答案可能对未来的一些开发人员有用。

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

解决了这个问题 我已经将代码捆绑在一个很棒的包中,现在它对你也一样,here's the link


以下是您如何实现可搜索下拉菜单来代替默认列表的方法:

1.安装:

pip install django-admin-searchable-dropdown

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

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. 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

提供的功能:

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

【讨论】:

    【解决方案2】:

    我不喜欢目前提供的所有解决方案。

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

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

    【讨论】:

      【解决方案3】:

      感谢@beholderrk、@gediminas 和@jk-laiho!我把它打包成reusable app

      安装:

      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),
          )
      

      它是这样的:

      【讨论】:

      • 有什么方法可以为模型过滤选定的 fk 吗?
      • @mujad,是的,请参阅上面示例和文档中的 RelatedDropdownFilter。
      • @PrateekGupta,你能更准确一点吗?你尝试了什么,发生了什么?如果问题真实且可重现,请在GitHub project 中提出问题。
      • @mrts 我按照你提到的步骤进行操作,首先使用 pip 安装它,然后将其添加到 INSTALLED_APPS 并最后添加到 admin.py 但过滤器部分仍然没有下拉列表。
      • @PrateekGupta 如果您对此答案有新的或后续问题,请提出新问题。
      【解决方案4】:

      能否举个完整的例子。它像以前一样显示。 这是我的代码

      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),
      
          )
      

      这是截图

      【讨论】:

        【解决方案5】:

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

        【讨论】:

        • 避免使用 djangosuit。我用过它,现在我被 django 1.8 卡住了,无法在不破坏一切的情况下更新到最新的 django。
        • suit 有一个版本 2.0 (github.com/darklow/django-suit/tree/v2),它与 ​​django 1.11(最新的稳定版本)兼容,据我所知,工作正常,但到目前为止缺乏良好的文档。另一种选择是使用 django jet github.com/geex-arts/django-jet,它还具有内置的自动完成支持(据我所知,尽管不适用于过滤器)。这样可以避免覆盖模板,这在更新 django 时可能会成为问题
        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

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

          然后,您需要在要在其中显示输出的表单或模板中执行以下 2 项操作:

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

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

            <select>
              {% for choices in object.details.all %}
                <option> {{ object.choice }} </option>
              {% endfor %}
            </select>
            

          【讨论】:

            【解决方案8】:

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

            【讨论】:

            • 我见过的最矫枉过正的反应:) 没有冒犯:+1:
            【解决方案9】:

            我无法评论答案,所以我会在这里添加到 beholderrk 的答案。

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

              from django.contrib.admin.filters import AllValuesFieldListFilter
              
              class DropdownFilter(AllValuesFieldListFilter):
                  template = 'admin/dropdown_filter.html'
              
            4. 现在你可以在你的管理类中使用这个过滤器了:

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

            效果很好!

            【讨论】:

            • 完美答案。在 Django 1.8 中为我工作。谢谢!
            • 优秀。在基于外键进行过滤时,我必须从 RelatedFieldListFilter 继承,但相同的模板有效。
            • 与 JK Laiho 类似,我必须从 ChoicesFieldListFilter 继承带有 choices kwarg 的字段。使用 AllValuesFieldListFilter 确实有效,但它显示的是值而不是人类可读的名称。
            • 对我来说结果总是空的,并且 DropdownFilter 显示不下拉......
            【解决方案10】:

            使用来自 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>
            

            【讨论】:

            • 对于遇到此问题的任何人:这是撰写本文时的正确方法,但请参阅 Gedas 的答案以了解更多详细信息。
            • 这是一个很好的答案。要更正先前评论的错字,请使用@Gediminas 答案here,其中详细说明了实现此目的的步骤。
            • 另外,可以添加一个“删除”选项,以便通过在最后两行之间添加以下内容({% endif %}&lt;/ul&gt;)轻松返回到“全部”选项:@987654325 @。我发现“删除”链接比在下拉菜单中选择“全部”要少得多。
            猜你喜欢
            • 2021-11-02
            • 2011-01-23
            • 1970-01-01
            • 2013-11-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-11-02
            • 2019-05-20
            相关资源
            最近更新 更多