Django REST Framework API Guide 08
1、Filtering
2、Pagination
FIltering
GenericAPIView的子类筛选queryset的简单方法是重写.get_quueryset()方法。
1、根据当前用户进行筛选 # self.request.user
2、根据当前URL # self.kwargs, url('^purchases/(?P<username>.+)/$', PurchaseList.as_view()),
3、根据当前url查询参数 # self.request.query_params
from myapp.models import Purchase
from myapp.serializers import PurchaseSerializer
from rest_framework import generics class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer def get_queryset(self):
"""
This view should return a list of all the purchases
for the currently authenticated user.
"""
user = self.request.user
return Purchase.objects.filter(purchaser=user)
API Guide
REST框架也包含支持通用筛选后端允许你构建复杂的查询和筛选,此时需要先引出DjangoFilterBackend模块
需要先安装django_filters,并将它添加到INSTALLED_APPS
pip install django-filter
DjangoFilterBackend
1、可以用全局设置
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
2、也可以对每个使用CBV格式的继承自GenericAPIView类的视图或者视图集单独设置。
from django_filters.rest_framework import DjangoFilterBackend class UserListView(generics.ListAPIView):
...
filter_backends = (DjangoFilterBackend,)
如果是需要简单的基于等式的过滤,你在工作视图类或者视图集类上可以设置filter_fields属性
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (DjangoFilterBackend,)
filter_fields = ('category', 'in_stock')
这将允许你对提供的字段创建一个FIlterSet类,允许你的request如下
http://example.com/api/products?category=clothing&in_stock=True
SearchFilter
SearchFilter类支持单独的查询参数查询,基于django admin的查询功能。
需要在类上设置search_fields属性集,必须是模型上的一组字段名
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.SearchFilter,)
search_fields = ('username', 'email')
此时允许客户端的筛选查询如下
http://example.com/api/users?search=russell
你也可以添加一个相关外键或者多对多字段查找
search_fields = ('username', 'email', 'profile__profession')
默认情况下,搜索将使用不区分大小写的部分匹配。搜索参数可以包含多个搜索项,它们应该是空白和/或逗号分隔的。如果使用多个搜索项,那么只有在所有提供的条件匹配时,对象才会返回到列表中。
搜索行为可以通过向search_fields字段添加各种字符来加以限制。
- '^' Starts-with search.
- '=' Exact matches.
- '@' Full-text search. (Currently only supported Django's MySQL backend.)
- '$' Regex search.
search_fields = ('=username', '=email')
默认查询参数是search,你可以用SEARCH_PARAM来改
OrderingFilter
默认url参数ordering,可以通过ORDERING_PARAM设置来重写。
http://example.com/api/users?ordering=username
http://example.com/api/users?ordering=-username
http://example.com/api/users?ordering=account,username
指定排序字段,可以通过类上的ordering_fields属性完成
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = ('username', 'email')
如果没有设置,也可以在serializer_class里面设置,如果您确信视图使用的查询集不包含任何敏感数据,那么还可以通过使用特殊值'__all__',显式地指定视图应该允许对任何模型字段或查询集聚合进行排序。
class BookingsListView(generics.ListAPIView):
queryset = Booking.objects.all()
serializer_class = BookingSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = '__all__'
指定一个默认排序
如果类上设置了ordering属性,将会被用来当做默认的排序。通常,您可以通过在初始查询集上设置order_by来控制这一点,但是使用视图上的ordering参数允许您以某种方式指定顺序,然后它可以自动地作为上下文传递到呈现的模板。如果列标题被用于排序结果,则可以自动呈现不同的列标题。
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = ('username', 'email')
ordering = ('username',)
DjangoObjectPermissionsFilter
DjangoObjectPermissionsFilter意在跟django-guardian包一起使用,添加客制化的视图权限。过滤器确保querysets只返回用户有合适视图权限的对象。
想要使用DjangoObjectPermissionsFilter,你也要添加一个合适的对象权限类,确保有合适权限的用户可以操作实例。最简单的方法就是使用DjangoObjectPermissionsFilter子类,并添加视图权限到perms_map属性。使用DjangoObjectPermissionsFilter和DjangoobjectPermissions的完整示例。
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'],
}
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,)
Pagination
当你使用通用视图或者视图集是分页才会自动执行。如果你使用的是一个常规的APIView,你需要自己去调用分页的API来确保结果是被分页好的响应。可以看一下mixins.ListModelMixin和generics.GenericAPIView的源码,可以通过设置分页的类为None来关闭分页。
设置分页样式
全局设置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 100
}
你也可以单独设置独立的视图的pagination_class属性
修改分页样式
class LargeResultsSetPagination(PageNumberPagination):
page_size = 1000
page_size_query_param = 'page_size'
max_page_size = 10000 class StandardResultsSetPagination(PageNumberPagination):
page_size = 100
page_size_query_param = 'page_size'
max_page_size = 1000
然后你可以应用新的样式通过在视图上使用.pagination_class属性
class BillingRecordsView(generics.ListAPIView):
queryset = Billing.objects.all()
serializer_class = BillingRecordsSerializer
pagination_class = LargeResultsSetPagination
或者你也可以把这个分页样式类设置成全局的
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'
}
API Reference
PageNumberPagination
此分页样式允许传入一个单独的page数字在请求中
GET https://api.example.org/accounts/?page=4
响应:
HTTP 200 OK
{
"count": 1023
"next": "https://api.example.org/accounts/?page=5",
"previous": "https://api.example.org/accounts/?page=3",
"results": [
…
]
}
全局设置PageNumberPagination,并设置PAGE_SIZE:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100
}
配置
PageNumberPagination类包含了很多属性,可以通过重写属性或者方法改变分页风格
1、django_paginator_class # 使用Django Paginator 类,默认django.core.paginator.Paginator
2、page_size # 每页显示条数
3、page_query_param # 一个字符串值,指示要用于分页控件的查询参数的名称。
4、page_size_query_param # 默认为空,如果设置,则是一个字符串值,指示允许客户端根据每个请求设置页面大小的查询参数的名称。
5、max_page_size # 如果设置,这是一个指示最大允许请求页面大小的数值。此属性仅在page_size_query_param也被设置时有效。
6、last_page_strings # 一个字符串值的列表或元组,指示可能与page_query_param一起用于请求集合中的最终页的值。默认('last', )
7、template # 可视化API的模板。默认"rest_framework/pagination/numbers.html"
LimitOffsetPagination
这种分页样式反映了查找多个数据库记录时使用的语法。客户端包括“限制”和“偏移”查询参数。该限制指示要返回的最大项目数,并且等同于其他样式中的page_size大小。偏移量指示查询相对于未分页项目的完整集合的起始位置。
GET https://api.example.org/accounts/?limit=100&offset=400
HTTP 200 OK
{
"count": 1023
"next": "https://api.example.org/accounts/?limit=100&offset=500",
"previous": "https://api.example.org/accounts/?limit=100&offset=300",
"results": [
…
]
}
配置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
}
自定义分页样式
创建自定义的分页序列化类,需要继承pagination.BasePagination并重写.paginate_queryset(self, queryset, request, view=None)和get_paginated_response(self, data)方法
1、paginate_queryset # 通过初始化queryset返回一个可迭代的对象仅包含请求页面的数据
2、get_paginated_response # 通过序列化页面的数据,返回一个Response实例
假设我们想用修改的格式替换默认的分页输出样式,该格式包括嵌套的“links”键中的下一链接和先前链接。我们可以指定像这样的自定义分页类:
class CustomPagination(pagination.PageNumberPagination):
def get_paginated_response(self, data):
return Response({
'links': {
'next': self.get_next_link(),
'previous': self.get_previous_link()
},
'count': self.page.paginator.count,
'results': data
})
设置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',
'PAGE_SIZE': 100
}
Django REST Framework API Guide 08的更多相关文章
- Django REST Framework API Guide 01
之前按照REST Framework官方文档提供的简介写了一系列的简单的介绍博客,说白了就是翻译了一下简介,而且翻译的很烂.到真正的生产时,就会发现很鸡肋,连熟悉大概知道rest framework都 ...
- Django REST Framework API Guide 03
本节大纲 1.Routers 2.Parsers 3.Renderers Routers Usage from rest_framework import routers router = route ...
- Django REST Framework API Guide 06
本节大纲 1.Validators 2.Authentication Validators 在REST框架中处理验证的大多数时间,您将仅仅依赖于缺省字段验证,或在序列化器或字段类上编写显式验证方法.但 ...
- Django REST Framework API Guide 04
本节大纲 1.serializers 1.Serializers Serializers允许复杂的数据,像queryset和模型实例转换成源生的Python数据类型.从而可以更简单的被渲染成JSON, ...
- Django REST Framework API Guide 02
本节大纲 1.Generic Views 2.ViewSets 1.Generic Views CBV的主要的一个优点就是极大的允许了对于代码的从用.自然,rest framework取其优势,提供 ...
- Django REST Framework API Guide 07
本节大纲 1.Permissions 2.Throttling Permissions 权限是用来授权或者拒绝用户访问API的不同部分的不同的类的.基础的权限划分 1.IsAuthenticated ...
- Django REST Framework API Guide 05
本节大纲 1.Serializer fields 2.Serializer relations Serializer fields 1.serializer 字段定义在fields.py文件内 2.导 ...
- Django Rest Framework API指南
Django Rest Framework API指南 Django Rest Framework 所有API如下: Request 请求 Response 响应 View 视图 Generic vi ...
- tastypie Django REST framework API [Hello JSON]
tastypie is a good thing. Haven't test it thoroughly. Gonna need some provement. Now I will introduc ...
随机推荐
- python接口自动化-post请求1
一.查看官方文档 1. 学习一个新的模块,直接用 help 函数就能查看相关注释或案例内容,例如 具体信息如下,可查看 python 发送 ge t和 post 请求的案例: F:\test-req- ...
- Python距离放弃又近了Day02
今天,来时大概复习了上一天讲过的一些计算机基础和简单数据类型和if语句,第二天就来了循环,还是个while的死循环,突然想到还是电脑好,不管循环多少次,只要电脑不崩溃,就能一直精准的算下去,这就和人不 ...
- day16--包的认识、循环导入、绝对导入、相对导入、模块的搜索路径等(待续)
''' 一系列功能模块的集合体 -- 包就是管理功能相近的一系列模块的文件夹 -- 该文件夹包含一个特殊文件__init__.py -- 文件夹名就是包名,产生的包名就是指向__init__.py的全 ...
- EF Core 多对多配置
1.配置2个数据表 T_Authors ,T_Books 2.新建控制台项目,安装EF驱动 PM> Install-Package Pomelo.EntityFrameworkCore.Mysq ...
- Elasticsearch 通关教程(三): 索引别名Aliases问题
业务问题 业务需求是不断变化迭代的,也许我们之前写的某个业务逻辑在下个版本就变化了,我们可能需要修改原来的设计,例如数据库可能需要添加一个字段或删减一个字段,而在搜索中也会发生这件事,即使你认为现在的 ...
- 让linux启动更快的方法
导读 进行 Linux 内核与固件开发的时候,往往需要多次的重启,会浪费大把的时间. 在所有我拥有或使用过的电脑中,启动最快的那台是 20 世纪 80 年代的电脑.在你把手从电源键移到键盘上的时候,B ...
- Day5 Numerical simulation of optical wave propagation之通过随机介质(如大气湍流)的传播(一)
一 分步光束传播方法 到目前为止,人们已经设计出传播算法,用于模拟通过真空和通过可用光线矩阵描述的简单光学系统的传播. 其中分步光束传播方法除了描述上述传播过程,还有更复杂的应用,包括:部分时间和空间 ...
- JVM调优:HotSpot JVM垃圾收集器
HotSpot JVM垃圾收集器 - Snooper - 博客园https://www.cnblogs.com/snooper/p/8718478.html
- Git各个状态之间转换指令总结
基本状态标识 A- = untracked 未跟踪 A = tracked 已跟踪未修改 A+ = modified - 已修改未暂存 B = staged - 已暂存未提交 C = committe ...
- 为什么String被设计为不可变?是否真的不可变?
1 对象不可变定义 不可变对象是指对象的状态在被初始化以后,在整个对象的生命周期内,不可改变. 2 如何不可变 通常情况下,在java中通过以下步骤实现不可变 对于属性不提供设值方法 所有的属性定义为 ...