drf 過濾器組件與自定義過濾器


一、使用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},


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM