Django REST framwork过滤

Django REST framework提供了内置的很多过滤方法(查询),文档非常详尽,例如 URL过滤,查询参数过滤。

内置过滤

第三方包

第三方包在特定环境下更为简便

Django URL Filter使用简介

django-url-filter提供了一个安全方式通过面向用户友好的URLs来过滤数据,文档可参考 Django URL Filter

  • 安装django-url-filter

pip install django-url-filter
  • 定制过滤

django-url-filter使用非常方便,并且和Django REST framework无缝结合,只需要简单指定过滤字段,就可以在URL中使用。

举例,原先DRF的视图代码如下:

from rest_framework import viewsets
from api.serializers import UserSerializer
from api.models import User

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all().order_by('create_time')
    serializer_class = UserSerializer

只需要添加url_filter过滤模块,然后再增加字段定义就可以:

from url_filter.integrations.drf import DjangoFilterBackend

from rest_framework import viewsets
from api.serializers import UserSerializer
from api.models import User

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all().order_by('create_time')
    serializer_class = UserSerializer
    filter_backends = [DjangoFilterBackend]
    filter_fields = ['username', 'email']

然后就可以在URL中使用如下查询:

# get user with id 5
example.com/users/?id=5

# get user with id either 5, 10 or 15
example.com/users/?id__in=5,10,15

# get user with id between 5 and 10
example.com/users/?id__range=5,10

# get user with username "foo"
example.com/users/?username=foo

# get user with username containing case insensitive "foo"
example.com/users/?username__icontains=foo

# get user where username does NOT contain "foo"
example.com/users/?username__icontains!=foo

# get user who joined in 2015 as per user profile
example.com/users/?profile__joined__year=2015

# get user who joined in between 2010 and 2015 as per user profile
example.com/users/?profile__joined__range=2010-01-01,2015-12-31

# get user who joined in after 2010 as per user profile
example.com/users/?profile__joined__gt=2010-01-01

Django REST framework - filtering against query param提供了参考

注意:实际上过滤的规则和Django相同,采用约定俗成的方法,例如,要选择时间范围:

假设数据库字段是create_time

api/users/?create_time__year=2018

# 注意:day时间范围是0:00,所以如果要查2018年2月2日全天数据,输入是 "2018-02-02,2018-02-03"
api/users/?create_time__range=2018-02-02,2018-02-03

api/users/?create_time__gte=2018-02-02&create_time__lt=2018-02-03

注意:在URL中传递"时间"需要做一个字符编码转换,例如

原始字符

转换URL(urlencode)

空格

+

:

%3a

通过google可以搜索到在线转换urlencode,不过,使用python很容易实现,见下文

举例:

  • 2017-11-10 11:02 转换到URL 2017-11-10+11%3a02

所以,如果要查询 2017-11-10 11:002017-11-10 11:10的数据,应该传递

api/users/?create_time__gte=2017-11-10+11%3a00&create_time__lt=2017-11-10+11%3a10

使用Python转换字符串

参考How to urlencode a querystring in Python?

Python2实现urlencode

Python 2使用 urllib.quote_plus 转换

>>> import urllib
>>> urllib.quote_plus('2017-11-10 11:02')
'2017-11-10+11%3A02'

Python3实现urlencode

在Python 3中,urllib包被分解成更小的组件,需要使用 urllib.parse.quote_plus

>>> import urllib.parse
>>> urllib.parse.quote_plus('2017-11-10 11:02')
'2017-11-10+11%3A02'

另外,在 cdown/gist:1163649 提供了一个shell脚本来转换

参考

Last updated