一、使用drf過濾器
-
drf過濾器:在GenericAPIView這個視圖基類的
def filter_queryset(self, queryset)
方法中,通過self.filter_backends
的配置來拿到過濾器並使用。但drf 默認在settings文件中的配置是空,既不使用過濾器。 -
drf默認為我們提供了兩個過濾器類
-
class OrderingFilter(BaseFilterBackend)
用於排序使用時: 在url添加配置中參與排序的字段
-
class SearchFilter(BaseFilterBackend)
用於搜索使用時: 在url添加配置中參與搜索的字段
-
-
如果我們要使用過濾器也可以通過局部配置和全局配置來進行使用
局部配置:
from rest_framework.generics import ListAPIView
# OrderingFilter排序、SearchFilter搜索
from rest_framework.filters import OrderingFilter, SearchFilter
class FreeCourseListAPIView(ListAPIView):
queryset = models.Course.objects.filter(is_delete=False, is_show=True).order_by(
"-orders").all()
serializer_class = serializers.FreeCourseModelSerializer
# 局部配置過濾器類
filter_backends = [OrderingFilter, SearchFilter]
# 參與排序的字段: ordering=-price,id,students
ordering_fields = ['price', 'id', 'students']
# 參與搜索的字段: search=python (name字段中帶python就ok)
search_fields = ['name', 'brief']
# 攜帶排序的過濾參數的url: http://127.0.0.1:8000/course/free?ordering=-price 降序
# 攜帶搜索的過濾參數的url: http://127.0.0.1:8000/course/free?search=python (name字段中帶python就ok)
二、自定義過濾器
- 自定義過濾器類。繼承
BaseFilterBackend
類(實際上看過源碼你就知道繼不繼承都可以,因為BaseFilterBackend
類並沒有做什么實質性的事情) - 實現def filter_queryset(self, request, queryset, view) 方法,必須返回一個queryset對象
自定義過濾器類
from rest_framework.filters import BaseFilterBackend
# 自定義過濾器類
class LimitFilter(BaseFilterBackend):
# 必須實現filter_queryset方法,返回queryset對象
def filter_queryset(self, request, queryset, view):
# 取出過濾條件
limit = request.query_params.get("limit") # 過濾參數
try:
return queryset[:int(limit)]
except:
return queryset
使用自定義過濾器類
from . import filters
class FreeCourseListAPIView(ListAPIView):
queryset = models.Course.objects.filter(is_delete=False, is_show=True).order_by(
"-orders").all()
serializer_class = serializers.FreeCourseModelSerializer
# 局部配置過濾器類
filter_backends = [filters.LimitFilter]
# 攜帶自定義過濾字段參數的url: http://127.0.0.1:8000/course/free?limit=1
三、使用django-filter模塊
django-filter模塊可以做一些更高級的過濾,也可以自定義過濾,比如分類篩選、篩選區間等
安裝依賴: pip install django-filter
django-filter模塊為django和drf都做了相應的支持。如果是drf做前后端分離的項目就使用from django_filters.rest_framework import DjangoFilterBackend
使用:
局部配置過濾器類:filter_backends = [DjangoFilterBackend]
參與分類篩選的字段:filter_fields = ['course_category']
(看源碼得知,其實源碼中反射了2個字段名,分別是:filterset_fields、filter_fields
,反射了兩個類名,分別是:filterset_class、filter_class、
)
# 分類篩選:django-filter:filter_backends配置DjangoFilterBackend,再在filter_fields中配置分組篩選的字段
from django_filters.rest_framework import DjangoFilterBackend
class FreeCourseListAPIView(ListAPIView):
queryset = models.Course.objects.filter(is_delete=False, is_show=True).order_by(
"-orders").all()
serializer_class = serializers.FreeCourseModelSerializer
# 局部配置過濾器類
filter_backends = [DjangoFilterBackend]
# 參與分類篩選的字段:
filter_fields = ['course_category']
# 攜帶分類篩選字段的參數的url: http://127.0.0.1:8000/course/free?course_category=2
3.1 基於django-filter模塊自定義過濾器類實現價格區間
- 自定義過濾器類。繼承
from django_filters.rest_framework.filterset import FilterSet
類 - 自定義分類篩選的字段。在Meta類中通過fields來指定篩選的字段。和定義序列化類方法一致
自定義過濾器類
# 基於django-filter插件,完成指定區間篩選(一般都是對應數字字段)
from django_filters.rest_framework.filterset import FilterSet
from django_filters import filters
from . import models
class CourseFilterSet(FilterSet):
# field_name:要過濾的數據庫字段,lookup_expr:過濾條件
min_price = filters.NumberFilter(field_name='price', lookup_expr='gte') # 條件:大於price
max_price = filters.NumberFilter(field_name='price', lookup_expr='lte') # 條件:小於price
class Meta:
model = models.Course
# 參與分類篩選的字段:
fields = ['course_category', 'max_price', 'min_price']
使用自定義過濾器類
# 分類篩選:django-filter:filter_backends配置DjangoFilterBackend,再在filter_fields中配置分組篩選的字段
from django_filters.rest_framework import DjangoFilterBackend
# 自定義過濾器類
from . import filters
class FreeCourseListAPIView(ListAPIView):
queryset = models.Course.objects.filter(is_delete=False, is_show=True).order_by(
"-orders").all()
serializer_class = serializers.FreeCourseModelSerializer
# 局部配置過濾器類
filter_backends = [DjangoFilterBackend]
# 使用基於django-filter自定義過濾器類
filter_class = filters.CourseFilterSet
# 攜帶分類篩選字段的參數的url: http://127.0.0.1:8000/course/free?min_price=20&max_price=80
自定義過濾器字段對照表
models.AutoField: {'filter_class': NumberFilter},
models.CharField: {'filter_class': CharFilter},
models.TextField: {'filter_class': CharFilter},
models.BooleanField: {'filter_class': BooleanFilter},
models.DateField: {'filter_class': DateFilter},
models.DateTimeField: {'filter_class': DateTimeFilter},
models.TimeField: {'filter_class': TimeFilter},
models.DurationField: {'filter_class': DurationFilter},
models.DecimalField: {'filter_class': NumberFilter},
models.SmallIntegerField: {'filter_class': NumberFilter},
models.IntegerField: {'filter_class': NumberFilter},
models.PositiveIntegerField: {'filter_class': NumberFilter},
models.PositiveSmallIntegerField: {'filter_class': NumberFilter},
models.FloatField: {'filter_class': NumberFilter},
models.NullBooleanField: {'filter_class': BooleanFilter},
models.SlugField: {'filter_class': CharFilter},
models.EmailField: {'filter_class': CharFilter},
models.FilePathField: {'filter_class': CharFilter},
models.URLField: {'filter_class': CharFilter},
models.GenericIPAddressField: {'filter_class': CharFilter},
models.CommaSeparatedIntegerField: {'filter_class': CharFilter},
models.UUIDField: {'filter_class': UUIDFilter},