1.自定义filter

  • 继承BaseFilterBackend

  • 定义filter_queryset函数

注意:只有在继承了GenericAPIView的视图类中才生效

 

 

 

 

 

 代码

from app01.models import UserInfo
from rest_framework import serializers
from rest_framework.viewsets import GenericViewSet
from rest_framework.viewsets import ModelViewSet
from rest_framework.filters import BaseFilterBackend


class UserModelSerializer(serializers.ModelSerializer):
    level_text = serializers.CharField(source='get_level_display', read_only=True)
    extra = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = UserInfo
        fields = ['username', 'age', 'email', 'level_text', 'extra']

    def get_extra(self, obj):
        print(obj)
        return 666


class Filter1(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        age = request.query_params.get('age')
        if not age:
            return queryset
        return queryset.filter(age__gt=age)


class Filter2(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        user_id = request.query_params.get('id')
        if not user_id:
            return queryset
        return queryset.filter(id__gt=user_id)


class User(ModelViewSet):
    filter_backends = [Filter1, Filter2]
    queryset = UserInfo.objects.all()
    serializer_class = UserModelSerializer

    def perform_create(self, serializer):
        serializer.save(password="123")

源码分析

 

 

 

2.第三方filter

在drf开发中有一个常用的第三方过滤器:DjangoFilterBackend。

2.1 安装注册

安装

pip install django-filter

注册app

INSTALLED_APPS = [
    ...
    'django_filters',
]

全局配置和应用:

# settings.py 全局配置

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend',]
}

 

2.2 简单使用

视图

 1 from app01.models import UserInfo
 2 from rest_framework import serializers
 3 from rest_framework.viewsets import GenericViewSet
 4 from rest_framework.mixins import ListModelMixin, \
 5     RetrieveModelMixin, \
 6     CreateModelMixin, \
 7     UpdateModelMixin, \
 8     DestroyModelMixin
 9 from rest_framework.viewsets import ModelViewSet
10 from rest_framework.filters import BaseFilterBackend
11 from django_filters.rest_framework import DjangoFilterBackend
12 
13 
14 class UserModelSerializer(serializers.ModelSerializer):
15     level_text = serializers.CharField(source='get_level_display', read_only=True)
16     extra = serializers.SerializerMethodField(read_only=True)
17 
18     class Meta:
19         model = UserInfo
20         fields = ['username', 'age', 'email', 'level_text', 'extra']
21 
22     def get_extra(self, obj):
23         print(obj)
24         return 666
25        return queryset.filter(id__gt=user_id)
26 
27 
28 class User(ModelViewSet):
29     filter_backends = [DjangoFilterBackend, ]
  
30 filterset_fields = ['id', 'age', 'email'] # 定义过滤的字段,是且的关系 31 queryset = UserInfo.objects.all() 32 serializer_class = UserModelSerializer 33 34 def perform_create(self, serializer): 35 serializer.save(password="123")

 

 

 2.3 进阶使用

自定义过滤器类,实现复杂的过滤筛选

视图

from rest_framework import serializers
from rest_framework.viewsets import ModelViewSet
from django_filters.rest_framework import DjangoFilterBackend, OrderingFilter
from django_filters import FilterSet, filters
from app01 import models


class UserModelSerializer(serializers.ModelSerializer):
    level_text = serializers.CharField(
        source="get_level_display",
        read_only=True
    )
    depart_title = serializers.CharField(
        source="depart.title",
        read_only=True
    )
    extra = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = models.UserInfo
        fields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]

    def get_extra(self, obj):
        return 666


class MyFilterSet(FilterSet):
    # /api/users/?min_id=2  -> id>=2
    min_id = filters.NumberFilter(field_name='id', lookup_expr='gte')

    # /api/users/?name=wupeiqi  -> not ( username=kunmzhao )
    name = filters.CharFilter(field_name="username", lookup_expr="exact", exclude=True)

    # /api/users/?depart=xx     -> depart__title like %xx%
    depart = filters.CharFilter(field_name="depart__title", lookup_expr="contains")

    # /api/users/?token=true      -> "token" IS NULL
    # /api/users/?token=false     -> "token" IS NOT NULL
    token = filters.BooleanFilter(field_name="token", lookup_expr="isnull")

    # /api/users/?email=xx     -> email like xx%
    email = filters.CharFilter(field_name="email", lookup_expr="startswith")

    # /api/users/?level=2&level=1   -> "level" = 1 OR "level" = 2(必须的是存在的数据,否则报错-->内部有校验机制)
    # level = filters.AllValuesMultipleFilter(field_name="level", lookup_expr="exact")
    level = filters.MultipleChoiceFilter(field_name="level", lookup_expr="exact", choices=models.UserInfo.level_choices)

    # /api/users/?age=18,20     -> age in [18,20]
    age = filters.BaseInFilter(field_name='age', lookup_expr="in")

    # /api/users/?range_id_max=10&range_id_min=1    -> id BETWEEN 1 AND 10
    range_id = filters.NumericRangeFilter(field_name='id', lookup_expr='range')

    # /api/users/?ordering=id     -> order by id asc
    # /api/users/?ordering=-id     -> order by id desc
    # /api/users/?ordering=age     -> order by age asc
    # /api/users/?ordering=-age     -> order by age desc
    ordering = filters.OrderingFilter(fields=["id", "age"])

    # /api/users/?size=1     -> limit 1(自定义搜索)
    size = filters.CharFilter(method='filter_size', distinct=False, required=False)
    
    class Meta:
        model = models.UserInfo
        fields = ["id", "min_id", "name", "depart", "email", "level", "age", 'range_id', "size", "ordering"]

    def filter_size(self, queryset, name, value):
        int_value = int(value)
        return queryset[0:int_value]


class UserView(ModelViewSet):
    filter_backends = [DjangoFilterBackend, ]
    filterset_class = MyFilterSet

    queryset = models.UserInfo.objects.all()
    serializer_class = UserModelSerializer

    def perform_create(self, serializer):
        """ 序列化:对请求的数据校验成功后,执行保存。"""
        serializer.save(depart_id=1, password="123")

lookup_expr有很多常见选择:

'exact': _(''),
'iexact': _(''),

'contains': _('contains'),
'icontains': _('contains'),
'startswith': _('starts with'),
'istartswith': _('starts with'),
'endswith': _('ends with'),  
'iendswith': _('ends with'),
    
'gt': _('is greater than'),
'gte': _('is greater than or equal to'),
'lt': _('is less than'),
'lte': _('is less than or equal to'),

'in': _('is in'),
'range': _('is in range'),
'isnull': _(''),
    
'regex': _('matches regex'),
'iregex': _('matches regex'),

 

3.内置filter

drf源码中内置了2个filter,分别是:OrderingFilter,SearchFilter

3.1 OrderingFilter

支持排序

from rest_framework import serializers
from rest_framework.viewsets import ModelViewSet
from app01 import models
from rest_framework.filters import OrderingFilter


class UserModelSerializer(serializers.ModelSerializer):
    level_text = serializers.CharField(
        source="get_level_display",
        read_only=True
    )
    depart_title = serializers.CharField(
        source="depart.title",
        read_only=True
    )
    extra = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = models.UserInfo
        fields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]

    def get_extra(self, obj):
        return 666


class UserView(ModelViewSet):
    filter_backends = [OrderingFilter, ]
    # ?ordering=id
    # ?ordering=-id
    # ?ordering=age
    ordering_fields = ["id", "age"]

    queryset = models.UserInfo.objects.all()
    serializer_class = UserModelSerializer

    def perform_create(self, serializer):
        """ 序列化:对请求的数据校验成功后,执行保存。"""
        serializer.save(depart_id=1, password="123")

 

3.2 SearchFilter

支持模糊搜索。

from rest_framework import serializers
from rest_framework.viewsets import ModelViewSet
from app01 import models
from rest_framework.filters import SearchFilter


class UserModelSerializer(serializers.ModelSerializer):
    level_text = serializers.CharField(
        source="get_level_display",
        read_only=True
    )
    depart_title = serializers.CharField(
        source="depart.title",
        read_only=True
    )
    extra = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = models.UserInfo
        fields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]

    def get_extra(self, obj):
        return 666


class UserView(ModelViewSet):
    # ?search=坤%赵
    filter_backends = [SearchFilter, ]
    search_fields = ["id", "username", "age"]

    queryset = models.UserInfo.objects.all()
    serializer_class = UserModelSerializer

    def perform_create(self, serializer):
        """ 序列化:对请求的数据校验成功后,执行保存。"""
        serializer.save(depart_id=1, password="123")

 

posted on 2022-11-16 10:24  阿明明  阅读(139)  评论(0编辑  收藏  举报