本文由Scarb发表于金甲虫的博客,转载请注明出处

Django REST framework 过滤器

1. 设置过滤器

与分页一样,过滤器也可以全局设置或者对某个View设置。

1.1 全局设置

要使用DjangoFilterBackend,首先要安装django_filters

1
pip install django-filter

修改settings.pyDEFAULT_FILTER_BACKENDS参数

1
2
3
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}

1.2 对某个View设置

修改View的filter_backendsfilter_fields参数

1
2
3
4
5
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (DjangoFilterBackend,)
filter_fields = ('category', 'in_stock')

2. DRF框架定义的过滤器

2.1 字段值过滤 DjangoFilterBackend

使用django-filter库的功能进行过滤,可以对模型的各个域进行筛选。

1
GET http://example.com/api/products/4675/?category=clothing&max_price=10.00

配置方法:

1
2
3
4
5
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (DjangoFilterBackend,)
filter_fields = '__all__'

2.2 搜索过滤器 SearchFilter

是DRF自带的Filter,提供对某些字段的搜索功能。

1
GET http://example.com/api/users?search=russell

配置方法:

1
2
3
4
5
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.SearchFilter,)
search_fields = ('username', 'email')

也可以搜外键或者多对多关系

1
search_fields = ('username', 'email', 'profile__profession')

默认的搜索是大小写敏感的,多个搜索短语用空格或者逗号分开。
如果提供多个搜索的短语,那么只会返回包含所有短语的对象。

配置参数

定义搜索域的时候可以指定一些搜索规则

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

比如

1
search_fields = ('=username', '=email')

默认的搜索参数是search可以修改SEARCH_PARAM来重载。

2.3 排序过滤器 OrderingFilter

提供了对某些字段排序的功能。

1
2
3
GET http://example.com/api/users?ordering=username      # 正序

GET http://example.com/api/users?ordering=-username # 倒序

配置方法:

1
2
3
4
5
6
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = ('username', 'email')
ordering = ('username',) # 默认排序字段

ordering_fields可以为__all__

权限过滤 DjangoObjectPermissionsFilter

使用django-guardian,提供模型和对象粒度的权限控制和过滤。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# permissions.py
class CustomObjectPermissions(permissions.DjangoObjectPermissions):
"""
Similar to `DjangoObjectPermissions`, but adding 'view' permissions.
"""
perms_map = {
'GET': ['%(app_label)s.view_%(model_name)s'],
'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
'HEAD': ['%(app_label)s.view_%(model_name)s'],
'POST': ['%(app_label)s.add_%(model_name)s'],
'PUT': ['%(app_label)s.change_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}
1
2
3
4
5
6
7
8
9
10
11
# views.py
class EventViewSet(viewsets.ModelViewSet):
"""
Viewset that only lists events if user has 'view' permissions, and only
allows operations on individual events if user has appropriate 'view', 'add',
'change' or 'delete' permissions.
"""
queryset = Event.objects.all()
serializer_class = EventSerializer
filter_backends = (filters.DjangoObjectPermissionsFilter,)
permission_classes = (myapp.permissions.CustomObjectPermissions,)
1
2
3
4
5
6
7
8
9
10
# models.py
class Event(models.Model):
name = models.CharField(max_length=255)
execute_count = models.IntegerField(default=0)

def __str__(self):
return self.name

class Meta:
permissions = (('view_event', 'View event'),)