DjangoRest中使用filter

DjangoRest中使用filter

在繼承了GenericAPIView以及其子類的view中可以設置filter_backends屬性來使用filter.

例如:

from rest_framework import filters

filter_backends = (filters.OrderingFilter, filters.SearchFilter)

filter分類

1. DjangoFilterBackend (django_filters.rest_framework中)

參考文檔 Integration with DRF

  • Using the new FilterSet simply requires changing the import path. Instead of importing from django_filters, import from the rest_framework sub-package. Your view class will also need to add DjangoFilterBackend to the filter_backends.

    from django_filters import rest_framework as filters
    
    class ProductList(generics.ListAPIView):
        queryset = Product.objects.all()
        serializer_class = ProductSerializer
        filter_backends = (filters.DjangoFilterBackend,)
        filterset_fields = ('category', 'in_stock')
    
  • If you want to use the django-filter backend by default, add it to the DEFAULT_FILTER_BACKENDS setting.

    # settings.py
    INSTALLED_APPS = [
        ...
        'rest_framework',
        'django_filters',
    ]
    
    REST_FRAMEWORK = {
        'DEFAULT_FILTER_BACKENDS': (
            'django_filters.rest_framework.DjangoFilterBackend',
            ...
        ),
    }
    
  • Adding a FilterSet with filterset_class

    To enable filtering with a FilterSet, add it to the filterset_class parameter on your view class.

    from rest_framework import generics
    from django_filters import rest_framework as filters
    from myapp import Product
    
    
    class ProductFilter(filters.FilterSet):
        min_price = filters.NumberFilter(field_name="price", lookup_expr='gte')
        max_price = filters.NumberFilter(field_name="price", lookup_expr='lte')
    
        class Meta:
            model = Product
            fields = ['category', 'in_stock', 'min_price', 'max_price']
    
    
    class ProductList(generics.ListAPIView):
        queryset = Product.objects.all()
        serializer_class = ProductSerializer
        filter_backends = (filters.DjangoFilterBackend,)
        filterset_class = ProductFilter
    
  • Using the filterset_fields shortcut

    You may bypass creating a FilterSet by instead adding filterset_fields to your view class. This is equivalent to creating a FilterSet with just Meta.fields.

    from rest_framework import generics
    from django_filters import rest_framework as filters
    from myapp import Product
    
    
    class ProductList(generics.ListAPIView):
        queryset = Product.objects.all()
        filter_backends = (filters.DjangoFilterBackend,)
        filterset_fields = ('category', 'in_stock')
    
    
    # Equivalent FilterSet:
    class ProductFilter(filters.FilterSet):
        class Meta:
            model = Product
            fields = ('category', 'in_stock')
    

    Note that using filterset_fields and filterset_class together is not supported.

    如何自定義FilterBackend

    filter_backends加入自定義的FilterBackend

    self.filter_backends += (UsersStateFilterBackend,)

    from rest_framework import filters
    from django.db.models import Q
    
    class UsersStateFilterBackend(filters.BaseFilterBackend):
    """
    Filter users objects.
    """
    def filter_queryset(self, request, queryset, view):
        request_data = request.GET
        is_active = request_data.get('is_active', '')
        if is_active == '0':
            queryset = OpsUser.objects.filter(Q(is_deleted=False), Q(is_active=False)).all().order_by('id')
        elif is_active == '1':
            queryset = OpsUser.objects.filter(Q(is_deleted=False), Q(is_active=True)).all().order_by('id')
    
        return queryset
    

2. SearchFilter (rest_framework.filters中)

  • The SearchFilter class will only be applied if the view has a search_fields attribute set. The search_fields attribute should be a list of names of text type fields on the model, such as CharField or TextField.

    from rest_framework import filters
    
    class UserListView(generics.ListAPIView):
        queryset = User.objects.all()
        serializer_class = UserSerializer
        filter_backends = [filters.SearchFilter]
        search_fields = ['username', 'email']
    

    This will allow the client to filter the items in the list by making queries such as:

    http://example.com/api/users?search=russell
    # 只需要russel匹配search_fields中任意item的限制規則
    

    You can also perform a related lookup on a ForeignKey or ManyToManyField with the lookup API double-underscore notation:

    search_fields = ['username', 'email', 'profile__profession']

  • By default, searches will use case-insensitive partial matches. The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched.

    # 例如以下請求
    # 需要russell,aaa同時匹配search_fields中任意item的限制規則
    http://example.com/api/users?search=russell,aaa
    
  • 可以通過在search_fields前面添加各種字符來限制搜索行爲

    • ‘^’ Starts-with search.
    • ‘=’ Exact matches.
    • ‘@’ Full-text search. (Currently only supported Django’s PostgreSQL backend.)
    • ‘$’ Regex search.

3. OrderingFilter (rest_framework.filters中)

  • The OrderingFilter class supports simple query parameter controlled ordering of results.

    from rest_framework import filters
    class UserListView(generics.ListAPIView):
        queryset = User.objects.all()
        serializer_class = UserSerializer
        filter_backends = [filters.OrderingFilter]
        ordering_fields = ['username', 'email']
        ordering = ['username']
    

    Note:

    • ordering 查詢結果集默認排序
    • ordering_fields API應在排序過濾器中允許的字段
  • 默認查詢參數爲ordering

    # order users by username
    http://example.com/api/users?ordering=username
    
    # reverse orderings by prefixing the field name with '-'
    http://example.com/api/users?ordering=-username
    
    # Multiple orderings
    http://example.com/api/users?ordering=account,username
    
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章