一、过滤
在使用DRF写平台的时候,或多或少都会有过滤的需求。而在DRF中常用的就是django-filter库了,django-filter库包括一个DjangoFilterBackend类,它支持REST Framework的高度可定制的字段过滤。
首先安装django-filter:
1 |
$ pip install django-filter |
然后将django-filters添加到Django的INSTALLED_APPS。在settings.py加上如下配置:
1 2 3 4 5 |
INSTALLED_APPS = [ 'rest_framework', 'django_filters', ... ] |
你现在应该将过滤器后端添加到设置中:
1 2 3 |
REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) } |
或者将过滤器后端添加到单个视图或视图集。
1 2 3 4 5 |
from django_filters.rest_framework import DjangoFilterBackend class UserListView(generics.ListAPIView): ... filter_backends = (DjangoFilterBackend,) |
如果你只需要简单的基于等式的过滤,则可以在视图或视图集上设置filter_fields
属性,列出你要过滤的一组字段。
1 2 3 4 5 |
class ProductList(mixins.ListModelMixin, viewsets.GenericViewSet): queryset = Product.objects.all() serializer_class = ProductSerializer filter_backends = (DjangoFilterBackend,) filter_fields = ('category', 'in_stock') |
这将自动为给定字段创建一个 FilterSet
类,并允许你发出如下请求:
1 |
http://example.com/api/products?category=clothing&in_stock=True |
对于更高级的过滤要求,你应该在视图上创建FilterSet
类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import django_filters from myapp.models import Product from myapp.serializers impoert ProductSerializer from rest_framework import filters from rest_framework import generics class ProductFilter(filters.FilterSet): min_price = django_filters.NumberFilter(name=’price’, lookup_type=”gte”) max_price = django_filters.NumberFilter(name=’price’, lookup_type=”lte”) # 行为: 名称中包含某字符,且字符不区分大小写 name = filters.CharFilter(name='name', lookup_expr='icontains') class Meta: model = Product fields = [‘category’, ‘in_stock’, ‘min_price’, ‘max_price’] |
此时,就需要设置:
1 2 3 4 5 |
class ProductList(mixins.ListModelMixin, viewsets.GenericViewSet): queryset = Product.object.all() serializer_class = ProductSerializer filter_backends = (filter.DjangoFilterBackend,) filter_class = ProductFilter |
你可以在 django-filter文档中阅读有关FilterSet
的更多信息。
二、搜索
过滤大部分都是等值查询或范围查询,当然也可以like查询。但如果要明确指定可以对哪些字段进行搜索,就可以使用search_fields属性,默认为可以对serializer_class属性指定的串行器上的任何可读字段进行搜索,搜索使用的是DRF自己的库,如下代码:
1 2 3 4 5 6 7 |
from rest_framework import filters class UserListView(mixins.ListModelMixin, viewsets.GenericViewSet): queryset = User.objects.all() serializer_class = UserSerializer filter_backends = (filters.SearchFilter,) search_fields = ('username', 'email') |
也可以使用双下划线在Foreign Key或ManyToManyField上执行相关查找:
1 |
search_fields = ('username', 'email', 'profile__profession') |
默认情况下,搜索将使用不区分大小写的部分匹配。搜索参数可以包含多个搜索项,它们应该是空格和/或逗号分隔。如果使用多个搜索项,则仅当所有提供的条款匹配时,才会在列表中返回对象。默认情况下,搜索参数被命名为“search”,但这可能会被SEARCH_PARAM设置覆盖。
可以通过在search_fields中加入一些字符来限制搜索行为,如下:
- ‘^’ :以xx字符串开始搜索
- ‘=’ :完全匹配
- ‘@’ :全文搜索(目前只支持Django的MySQL后端)
- ‘$’ :正则表达式搜索
三、排序
DRF的OrderingFilter类支持简单的查询参数控制结果排序。默认情况下,查询参数被命名为“ordering”,但这可能会被ORDERING_PARAM设置覆盖。
可以使用ordering_fields属性明确指定可以对哪些字段执行排序,这有助于防止意外的数据泄露,例如允许用户对密码散列字段或其他敏感数据进行排序。
如果不指定ordering_fields属性,则默认为可以对serializer_class属性指定的串行器上的任何可读字段进行过滤。
1 2 3 4 5 |
class UserListView(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer filter_backends = (filters.OrderingFilter,) ordering_fields = ('username', 'email') |
如果在视图上设置了ordering
属性,则将用作默认排序。比如默认降序排序:ordering = ('-username',)
关于过滤、搜索、排序的测试工作,都可以在DRF提供的可浏览API页面看到效果,非常好用。
<摘录>
http://drf.jiuyou.info/#/drf/filtering?id=orderingfilter