安装配置

基本概念

filterset:

filterset类.过滤集.在meta类中要指定一个model.和fields.model类的fields字段中的属性会被添加到过滤条件中.同时可以定义此类的类属性,类属性均为额外过滤字段.类属性过滤字段,无需再meta中的feilds中声明即可添加过滤.这点与serializer并不相同.

filter:

filter.过滤器.针对某一个字段来详细定义过滤的情况.值的预处理,单字段过滤逻辑均在此类中.fitler的实例通常被用作filterset类的类属性.

安装命令

pip install django-filter

配置文件

在settings.py中安装并配置django_filters应用:

  1. INSTALLED_APPS = [
  2. ...
  3. 'django_filters',
  4. ]
  5. REST_FRAMEWORK = {
  6. ...
  7. # 过滤器默认后端,通常还会加上ordering和search组成三兄弟
  8. 'DEFAULT_FILTER_BACKENDS': [
  9. 'django_filters.rest_framework.DjangoFilterBackend',
  10. 'rest_framework.filters.SearchFilter',
  11. 'rest_framework.filters.OrderingFilter',
  12. ],
  13. }

使用流程

示例准备

模型
  1. class Project(models.Model):
  2. name = models.CharField(max_length=200,verbose_name='项目名')
  3. start_date = models.DateField(blank=True, null=True,verbose_name='开始日期')
  4. stars = models.IntegerField(null=True,blank=True,verbose_name="星星")
  5. spm = models.ForeignKeyField('User', blank=True, null=True,verbose_name='负责人')
  6. class Meta:
  7. verbose_name = "项目"
  8. class User(models.Model):
  9. username = models.CharField(max_length=200,verbose_name='用户名')
  10. class Meta:
  11. verbose_name = "用户"

序列化器
  1. class ProjectSerializer(serializers.ModelSerializer):
  2. class Meta:
  3. model = Project
  4. fields = "__all__"

视图
  1. class ProjectViewSet(ViewSets.ModelViewSet):
  2. queryset = Project.objects.all()
  3. serializer_class = ProjectSerializer

自定义过滤器

按照<项目名><等于>过滤

过滤器类
  1. import django_filters as filters
  2. from .models import Project
  3. class ProjectFilter(filters.FilterSet):
  4. class Meta:
  5. model = Project # 模型名
  6. fields = ['name',]

更新视图
  1. class ProjectViewSet(ViewSets.ModelViewSet):
  2. queryset = Project.objects.all()
  3. serializer_class = ProjectSerializer
  4. filterset_class = BookFilter # 过滤类

前端传参
  1. const name = 'prj1'
  2. axios.get(url,{params:{name}})

这样就实现了根据项目名等于prj1来过滤项目了.

捷径

在使用默认参数的时候(字段名等于某值)的时候,视图中可以如此简写

  1. class ProjectViewSet(ViewSets.ModelViewSet):
  2. queryset = Project.objects.all()
  3. serializer_class = ProjectSerializer
  4. filterset_fields = ['name'] # 不指定过滤类而直接指定过滤字段,与过滤类中meta类中的fields的值写法相同.

更多过滤条件(大于/小于等)

过滤器类
  1. class ProjectFilter(filters.FilterSet):
  2. class Meta:
  3. model = Project # 模型名
  4. fields = {"stars":["lte","gte"]}

前端传参
  1. const stars__lte = 13
  2. axios.get(url,{params:{stars__lte}})

这样就可以获得星星数小于13的所有项目了.

此时fields的值从列表/元组变为了字典, 字典中的键必须是model的合法属性名, 每个键的值是django支持的lookup中的一员, 前端传参的时候用双下划线链接字段与lookup即可正确使用.同样的,捷径中也支持这种字典的写法.

附录:lookup的全集

自定义前端传参的字段名

很多时候我们不希望暴露双下划綫语法,或者希望能获得一个更加可读的query参数,此时可以使用自定义字段来完成.

过滤器类
  1. class ProjectFilter(filters.FilterSet):
  2. min_stars = filters.NumberFilter(field_name="stars", lookup_expr='gte')
  3. class Meta:
  4. model = Project # 模型名
  5. fields = ('min_stars',)

前端传参
  1. const min_stars = '13'
  2. axios.get(url,{params:{min_stars}})

这样min_stars就替代了stars__gte作为传参的键了.

自定义过滤方法

过滤器类
  1. class ProjectFilter(filters.FilterSet):
  2. mine = filters.CharFilter(method='filter_mine') # 传入了method函数后,过滤器不再校验字段是否存在于模型上
  3. class Meta:
  4. model = Project # 模型名
  5. fields = ('mine',)
  6. def filter_mine(self, queryset, name, value):
  7. #函数名必须和上面定义的字符串相同,接受4个参数,request是当前请求,queryset是当前查询集,name是当前字段名,value是当前字段值.此函数返回值必须是一个queryset.
  8. return queryset.filter(Q(collectors=self.request.user)).distinct()

内置filter

CharFilter UUIDFilter BooleanFilter ChoiceFilter TypedChoiceFilter MultipleChoiceFilter TypedMultipleChoiceFilter DateFilter TimeFilter DateTimeFilter IsoDateTimeFilter DurationFilter ModelChoiceFilter ModelMultipleChoiceFilter NumberFilter NumericRangeFilter RangeFilter DateRangeFilter DateFromToRangeFilter DateTimeFromToRangeFilter IsoDateTimeFromToRangeFilter TimeRangeFilter AllValuesFilter AllValuesMultipleFilter LookupChoiceFilter

这些filter大部分都是在做字段值的预处理(类型转化/校验).比较重要的参数有

field_name
  • 需要被过滤的模型字段,也就是你model字段指向的模型类的一个字段属性(例如上文的name,或者stars).
  • 如果这个参数没有被指定,会选取过滤器在filterset类中的属性名作为默认值

    1. class ProjectFilter(filters.FilterSet):
    2. stars = filters.NumberFilter()
    3. class Meta:
    4. model = Project # 模型名
    5. fields = ('stars',)
    6. # 此时直接传stars就是按照星星数准确过滤了,如果写成star并且Project模型中找不到这个名字,会报错
  • 这个字段支持关系分隔符__例如:Project的manufacturer__name

    lookup_expr
  • 查询的lookup.默认值是exact.同样支持__语法.比如一个datetime类型字段的year_lt

    内置常用过滤器行为描述

    1.CharFilter

    字符串过滤器,没啥好说的.注意当你把一个原本是BooleanField的字段设置为CharFilter的时候,它的值只能是1或者0才能被正确过滤.

    2.BooleanFilter

    布尔过滤器,(True, 'True', 'true', '1')这些值是true,(False, 'False', 'false', '0')这些值是false,其他所有值都是None.当值为None时,不执行过滤.

    3.ChoiceFilter

    选项过滤器.仍然需要使用choice的值而不是key.但是会根据choices的参数做校验,从而返回一个not valid choice的异常.如果针对一个choice的字段使用了charfilter.那么传入非法选项的时候.如果类型也相同,会返回空值,否则一般会有类型转换错误.使用必要不是很强烈.

    4.MultipleChoiceFilter

    多选过滤器
    多选字段的传参: 在query中使用同一个键名传入多个参数. 例如/plantest/plan_tasks/?page=1&page_size=3&result_status=1&result_status=2这样就可以同时过滤即等于1又等于2的值了.

5.ModelChoiceFilter

模型类过滤器.根据外键值来过滤.非法值同样会抛出not valid choice.但是需要传入queryset参数.可以通过此参数来限制备选的值(例如分配任务时排除管理员.)

6.ModelMultipleChoiceFilter

模型类多选过滤.没啥好说的.