在drf开发中有一个常用的第三方过滤器:DjangoFilterBackend。
pip install django-filter
注册app:
INSTALLED_APPS = [...'django_filters',...]
基本搜索
# views.pyfrom rest_framework import serializersfrom rest_framework.viewsets import ModelViewSetfrom django_filters.rest_framework import DjangoFilterBackendfrom app01 import modelsclass UserModelSerializer(serializers.ModelSerializer):level_text = serializers.CharField(source="get_level_display",read_only=True)extra = serializers.SerializerMethodField(read_only=True)class Meta:model = models.UserInfofields = ["username", "age", "email", "level_text", "extra"]def get_extra(self, obj):return 666class UserView(ModelViewSet):filter_backends = [DjangoFilterBackend, ]filterset_fields = ["id", "age", "email"]queryset = models.UserInfo.objects.all()serializer_class = UserModelSerializerdef perform_create(self, serializer):""" 序列化:对请求的数据校验成功后,执行保存。"""serializer.save(depart_id=1, password="123")
复杂搜索
类的方式配置搜索条件FilterSet、filters
from rest_framework import serializersfrom rest_framework.viewsets import ModelViewSetfrom django_filters.rest_framework import DjangoFilterBackendfrom django_filters import FilterSet, filtersfrom app01 import modelsclass 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.UserInfofields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]def get_extra(self, obj):return 666class MyFilterSet(FilterSet):depart = filters.CharFilter(field_name="depart__title", lookup_expr="exact")min_id = filters.NumberFilter(field_name='id', lookup_expr='gte')class Meta:model = models.UserInfofields = ["min_id", "depart"]class UserView(ModelViewSet):filter_backends = [DjangoFilterBackend, ]filterset_class = MyFilterSetqueryset = models.UserInfo.objects.all()serializer_class = UserModelSerializerdef perform_create(self, serializer):""" 序列化:对请求的数据校验成功后,执行保存。"""serializer.save(depart_id=1, password="123")
高级搜索
from rest_framework import serializersfrom rest_framework.viewsets import ModelViewSetfrom django_filters.rest_framework import DjangoFilterBackend, OrderingFilterfrom django_filters import FilterSet, filtersfrom app01 import modelsclass 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.UserInfofields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]def get_extra(self, obj):return 666class MyFilterSet(FilterSet):# /api/users/?min_id=2 -> id>=2min_id = filters.NumberFilter(field_name='id', lookup_expr='gte')# /api/users/?name=wupeiqi -> not ( username=wupeiqi )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 NULLtoken = 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 10range_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 descordering = 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.UserInfofields = ["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 = MyFilterSetqueryset = models.UserInfo.objects.all()serializer_class = UserModelSerializerdef 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'),
全局配置和应用:
# settings.py 全局配置REST_FRAMEWORK = {'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend',]}
