Django Rest Framework之过滤器
Django Rest Framework之过滤器
一:原始过滤方法
默认情况下 DRF generic list view 会返回整个 queryset 查询结果,但通常业务只是需要其中一部分,这种情况下就需要使用 “过滤器” 来限制返回结果集。
最原始的方式是继承 GenericAPIView 类或使用继承了 GenericAPIView 的类,然后重写 .get_queryset() 方法 比如:
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
# queryset = Goods.objects.all()
serializer_class = GoodsSerializer
pagination_class = Pagination
def get_queryset(self):
queryset = Goods.objects.all()
price_min = self.request.query_params.get('price_min', 0)
if price_min:
queryset = Goods.objects.filter(shop_price__gt = int(price_min))
return queryset
这里注意:由于在类中没有指定queryset,在访问接口时会报如下错误
assert queryset is not None, '`basename` argument not specified, and could ' \
AssertionError: `basename` argument not specified, and could not automatically determine the name from the viewset, as it does not have a `.queryset` attribute.
解决方案是在路由中加basename参数:
from rest_framework.routers import DefaultRouter
from goods import views
router = DefaultRouter()
router.register(r'^goods', views.GoodsListViewSet, basename = 'goods')
这样即可在接口url中添加查询参数过滤数据:
这样做如果在过滤条件复杂的情况下,代码会显得过于冗余,而且有可能大部分代码一直在重复实现类似的功能。
二:DjangoFilterBackend
文档:https://www.django-rest-framework.org/api-guide/filtering/#djangofilterbackend
安装django-filter:
pip install django-filter
注册APP:
INSTALLED_APPS = [
'django_filters'
]
DjangoFilterBackend为默认的过滤类:
# 可以在settings配置文件添加如下选项,因为是默认的类,不添加也可
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}
在视图类中指定过滤类:
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = Goods.objects.all()
serializer_class = GoodsSerializer
pagination_class = Pagination
filter_backends = [DjangoFilterBackend]
filter_fields = ['name', 'shop_price'] # 需要过滤的字段
再次访问接口时,页面会多出一个Filter的按钮
注意:上面的商品名必须要与数据库中的已有商品名完全一致才可以被过滤出来(不同于模糊搜索)
现在需求变了,如:name字段需要模糊过滤,而price字段可以是一个价格区间。
那么可以通过自定义的过滤类来扩展默认的过滤类功能
from django_filters import rest_framework as filters
from goods.models import Goods
class GoodsFilter(filters.FilterSet):
# 自定义商品的过滤类
name = filters.CharFilter(field_name = 'name', lookup_expr='icontains') # 等价于 sql 中的 like; i 表示忽略大小写
min_price = filters.NumberFilter(field_name='shop_price', lookup_expr='gte')
max_price = filters.NumberFilter(field_name='shop_price', lookup_expr='lte')
class Meta:
model = Goods
fields = ['name', 'min_price', 'max_price']
视图类中使用自定义的过滤类:
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = Goods.objects.all()
serializer_class = GoodsSerializer
pagination_class = Pagination
filter_backends = [DjangoFilterBackend]
filter_fields = ['name', 'shop_price']
filter_class = GoodsFilter
三:SearchFilter
这个类提供了对单一字段的搜素功能,在使用后 DRF 数据浏览页面会出现 SearchFilter 的控制器。在配置时只需要将 view 中添加 search_fields 属性,且将需要搜索的 Model 字段放入 tuple 中传给 search_fields。
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = Goods.objects.all()
serializer_class = GoodsSerializer
pagination_class = Pagination
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filter_fields = ['name', 'shop_price']
filter_class = GoodsFilter
search_fields = ['name', 'goods_brief', 'goods_desc']
默认情况下,搜索是大小写敏感的局部匹配。搜索参数可以包含多个搜索定义,且用空格或者逗号分开。如果使用了多个查询字段则返回结果集必须符合所有所有字段查询条件。
查询设置:
'^' Starts-with search.
'=' Exact matches.
'@' Full-text search 模糊查询 (Currently only supported Django's MySQL backend.)
'$' Regex search
如:search_fields = (’@username’, ‘=email’)
四:OrderingFilter
OrderingFilter 类支持对单个查询字段结果集进行排序。
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = Goods.objects.all()
serializer_class = GoodsSerializer
pagination_class = Pagination
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filter_fields = ['name', 'shop_price']
filter_class = GoodsFilter
search_fields = ['name', 'goods_brief', 'goods_desc']
ordering_fields = ['sold_num', 'add_time']
上一篇: 送了一个茶叶蛋说一个搞笑囧段
推荐阅读
-
Django REST Framework批量更新rest_framework_extensions
-
Django Rest Framework之认证
-
Django rest framework基本介绍与代码示例
-
Django-Rest-Framework 权限管理源码浅析(小结)
-
Django REST Framework之版本控制
-
Django Rest framework之认证的实现代码
-
View + django-rest-framework序列化
-
Django Rest Framework源码剖析(五)-----解析器
-
django-rest-framework框架 第四篇 认证Authentication
-
Django REST framework