django框架最大的优势就是帮我们内置了一个开箱即用的管理后端,虽然样式上略显粗糙,不太符合国人的审美,但不得不说功能还是非常强大,并且还不断跟随django本身进行更新升级,如果要选后端的管理模板的话,我自己还是比较喜欢原生这个管理后端,把不符合需求的页面重写,也非常方便,并且它内置的一些功能也能很好的利用,比起参差不齐的第三方管理后端,我个人认为要好很多!

在实际项目中,往往有些需求就是让客户弄得非常复杂,其实用户都不一定理解他这么做的目的,但作为开发者,我们对需求往往是没有发言权的,更多时候是考虑如何实现客户的需求!

那么,自定义过滤筛选功能这块我相信很多人都会遇到,今天就带大家了解下,如何自定义django管理后端的过滤器!

在django后端注册一个模型,我们一般会继承ModelAdmin这个类,这个类有一个list_filter的属性,设置list_filter便可以激活管理更改列表页面右侧的侧栏过滤器,如下图所示:

java list stram 过滤之前的元素_python

list_filter 应是一个元素的列表或元组,其中每个元素应是下列类型之一:

一个字段名,其中指定的字段应该是 BooleanField``、CharFieldDateFieldDateTimeFieldIntegerFieldForeignKeyManyToManyField,例如:

class PersonAdmin(admin.ModelAdmin):
    list_filter = ('is_staff', 'company')

list_filter 中的字段名也可以使用 __ 查找来跨越关系,例如:

class PersonAdmin(admin.UserAdmin):
    list_filter = ('company__name',)

虽然,很多时候这个已经能很好的满足我们基本的需求,但难免有一些比较烧脑的需求,就需要我们去定制这个过滤器,那么我们该如何做呢?

只需要继承 django.contrib.admin.SimpleListFilter 的类,还需要为期提供 titleparameter_name 属性,并覆盖 lookupsqueryset 方法,例如:

from datetime import date

from django.contrib import admin
from django.utils.translation import gettext_lazy as _

class DecadeBornListFilter(admin.SimpleListFilter):
    # 自定义过滤器
   	# title顾名思义就是定义这个过滤器的名称
    title = _('decade born')

    # parameter_name指的是get请求的参数名,也就是url/?decade=''
    parameter_name = 'decade'

    def lookups(self, request, model_admin):
        """
        重写该lookups方法来定义过滤器需要显示的内容
        这个应该返回的是一个二元元组,或者二元列表元组都可以
        其中每项元组的第一个值为url中decade参数的值,第二个值为人类可读的显示在过滤器列表的项
        一般我们进行筛选的时候利用queryset方法的values_list方法筛选的格式正好符合要求!
        可以直接作为返回值,无需二次构造数据结构!
        """
        return (
            ('80s', _('in the eighties')),
            ('90s', _('in the nineties')),
        )

    def queryset(self, request, queryset):
        """
        重写这个queryset方法就可以根据url中传的参数去筛选列表的值
        两个参数分别为request和queryset,其中request参数与普通视图的request参数是一致的
        queryset代表的是该模型的列表,要根据当前列表筛选,只需要在queryset数据层再加一层filter筛选即可
        """
        # 注意:这里的self.value()获取的就是当前url中参数的值,其他的就按正常的视图筛选过滤操作即可
        if self.value() == '80s':
            return queryset.filter(birthday__gte=date(1980, 1, 1),
                                    birthday__lte=date(1989, 12, 31))
        if self.value() == '90s':
            return queryset.filter(birthday__gte=date(1990, 1, 1),
                                    birthday__lte=date(1999, 12, 31))

# 使用以上过滤器只需要将我们定义好的引入到list_filter中即可
class PersonAdmin(admin.ModelAdmin):
    list_filter = (DecadeBornListFilter,)

当然你还可以很轻松的自定义他的模板显示样式:

class FilterWithCustomTemplate(admin.SimpleListFilter):
    template = "custom_template.html"

具体的例子请看 Django 提供的默认模板(admin/filter.html)。