DRF的Filter:字段过滤,查找,排序
字段过滤
一般过滤可以重写get_queryset方法实现,这时候就可以去掉queryset这个属性了:
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): serializer_class = GoodsSerializer pagination_class = GoodsPagination # 覆写GenericAPIView下的该方法,以实现自己对query_set的返回加一些逻辑 def get_queryset(self): # 获取url参数中传过来的"要查询的商品的价格阈值",如果没有传就设置为0 price_min = self.request.query_params.get("price_min", 0) return Goods.objects.filter(shop_price__gt=price_min).order_by("shop_price")
现在就可以通过在url里指定参数price_min来实现对获取到的商品价格的过滤了。
注意在使用这种方法时,要在router.register里配置base_name,不然运行不了。
还可以使用django-filter,这个要把它注册为app,然后就能用了(因为这时候不需要重写get_queryset方法了,所以就需要把queryset这个属性拿回来)。然后可以自定义一个filters.py用来写自定义过滤规则的过滤器:
from django_filters import rest_framework as filters from .models import Goods class GoodsFilter(filters.FilterSet): """商品的过滤类""" # 区间查询,指定区间的最大最小值 min_price = filters.NumberFilter(field_name="shop_price", lookup_expr='gte') max_price = filters.NumberFilter(field_name="shop_price", lookup_expr='lte') # 模糊查询,这里带i是忽略大小写 name = filters.CharFilter(field_name="name", lookup_expr="icontains") class Meta: model = Goods fields = ['min_price', 'max_price', 'name']
然后在views.py的相关视图类里指定filter_class为这个自定义的过滤器类:
from .filters import GoodsFilter class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): serializer_class = GoodsSerializer pagination_class = GoodsPagination filter_backends = (DjangoFilterBackend,) queryset = Goods.objects.all() # filter_fields = ('name', 'shop_price') filter_class = GoodsFilter
在这个例子里配置完了之后,效果就是可以在url里指定min_price和max_price的值,来控制所返回的JSON中上shop_price值所在的区间,实现区间过滤;使用name实现模糊查询。
查找
要实现查找,只要在视图层配置filters.SearchFilter和search_fields=要查找的字段元组即可:
from rest_framework import filters class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): serializer_class = GoodsSerializer pagination_class = GoodsPagination filter_backends = (DjangoFilterBackend, filters.SearchFilter) queryset = Goods.objects.all() # filter_fields = ('name', 'shop_price') filter_class = GoodsFilter search_fields = ('name', 'goods_brief', 'goods_desc')
一些符号可以实现复杂的查找方式,比如以。。开头,全文搜索之类的。
排序
要实现排序,只要在视图层配置filters.OrderingFilter和ordering_fields=要排序的字段即可:
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): serializer_class = GoodsSerializer pagination_class = GoodsPagination filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter) queryset = Goods.objects.all() # filter_fields = ('name', 'shop_price') filter_class = GoodsFilter search_fields = ('name', 'goods_brief', 'goods_desc') ordering_fields = ('sold_num', 'add_time')