【问题标题】:Django admin reset search box query on filter selectionDjango管理员重置过滤器选择的搜索框查询
【发布时间】:2020-08-13 07:28:13
【问题描述】:

我在模型的 Django 管理中有以下类:

class TopUpsAdmin(admin.ModelAdmin):
    search_fields = ('user__email', 'user__phone_number',)
    list_filter = ('status',)

目前过滤器的默认行为是

if search box in the listing page is input with test_1 which is a user name and search up the result(url will have the following parameter /?q=test_1) , if select an option in the filter then the filter results also got affected by the search box query on the URL ?q=test_1&status__exact=1)

我不希望在选择过滤器时让搜索结果过滤列表。

阅读 Django docs 仅向我提供了如何使用参数中存在的查询(来自搜索框)覆盖过滤器。

任何帮助将不胜感激

【问题讨论】:

  • 如果用户想要同时进行搜索和过滤怎么办?我认为它应该保持原样,并让用户在需要时清除搜索输入。
  • @xyres 我明白,但目前我需要根据我的应用程序的要求重置过滤器选项上的搜索结果

标签: python django django-admin


【解决方案1】:

创建一个Admin SimpleListFilter 并应用以下mixin

from django.utils.translation import gettext_lazy as _

class FilterMixin:
    def choices(self, changelist):
        yield {
            'selected': self.value() is None,
            'query_string': changelist.get_query_string(remove=[self.parameter_name, 'q']),
            'display': _('All'),
        }
        for lookup, title in self.lookup_choices:
            yield {
                'selected': self.value() == str(lookup),
                'query_string': changelist.get_query_string({self.parameter_name: lookup}, remove=['q']),
                'display': title,
            }

完整的代码库

#models.py
class Person(models.Model):
    class GenderChoice(models.IntegerChoices):
        MALE = 1
        FEMALE = 2
        OTHER = 3

    name = models.CharField(max_length=20)
    gender = models.IntegerField(choices=GenderChoice.choices)

    def __str__(self):
        return self.name

# admin.py
class GenderFilter(FilterMixin, admin.SimpleListFilter):
    title = 'Gender'
    parameter_name = 'gender'

    def lookups(self, request, model_admin):
        return Person.GenderChoice.choices

    def queryset(self, request, queryset):
        if self.value():
            return queryset.filter(**{'gender': int(self.value())})
        else:
            return queryset


class PersonAdmin(admin.ModelAdmin):
    search_fields = ('name',)
    list_filter = (GenderFilter,)


admin.site.register(Person, PersonAdmin)

【讨论】:

  • 非常有用,我不知道FilterMixin,所以帮了大忙!
  • 在 Django 中没有名为 FilterMixin 的类,我创建它是因为它可以在每个 SimpleListFilter 类中重用以获得相同的行为。 @LinhNguyen
  • 哦,这不是基础类吗?然后我可以把选择放在 GenderFilter 中 :)
  • 是的,当然。但是,我不喜欢这样,因为它会破坏可读性。此外,如果您希望在许多过滤器中具有相同的行为(假设您有 3 个 list_filter 项目),c&p choices() 代码将是一个丑陋的过程。
【解决方案2】:

我认为您可以覆盖get_search_results 方法。见文档:https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_search_results

例子:

class PersonAdmin(admin.ModelAdmin):
    list_display = ('name', 'age')
    search_fields = ('name',)

    def get_search_results(self, request, queryset, search_term):
        if len(request.GET) > 1:
            search_term = None
        queryset, use_distinct = super().get_search_results(request,
                                                            queryset,
                                                            search_term)
        return queryset, use_distinct

【讨论】:

    猜你喜欢
    • 2011-03-04
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 2021-01-01
    • 2023-03-06
    相关资源
    最近更新 更多