分页与限流
# 分页与限流
# 分页
对于大量数据的传输需要进行分页操作。
REST framework已经实现了分页api。它支持:
- 将分页的链接作为响应内容的一部分,这是默认的方案。
- 在响应头中包含分页链接,如
Content-Range
或Link
。
注意只有在使用通用视图或视图集时,分页才会自动执行。如果你使用一个常规的APIView,你需要自己调用分页API来确保你返回一个分页的响应。
# 分页设置
REST framework中可以对分页功能进行全局设置,例如:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 100
}
2
3
4
注意
需要同时设置DEFAULT_PAGINATION_CLASS
和PAGE_SIZE
,它们的默认值都为None,表示不使用分页。
还可以使用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
2
3
4
5
6
7
8
9
然后你可以使用pagination_class
属性将你的新样式应用到视图中:
class BillingRecordsView(generics.ListAPIView):
queryset = Billing.objects.all()
serializer_class = BillingRecordsSerializer
pagination_class = LargeResultsSetPagination
2
3
4
当然也可以进行全局配置。
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'
}
2
3
# DRF内置分页类
# PageNumberPagination
这是一个简单的页码分页类。
请求案例
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": [
…
]
}
2
3
4
5
6
7
8
9
# 使用
同分页设置一样,全局使用配置如下:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100
}
2
3
4
也可以在GenericAPIView
的子类通过在每个视图中设置pagination_class
属性来应用分类。
# 配置
可以像上面一样复写下面的属性,来修改分类样式。
django_paginator_class
- django框架分页类。默认使用django.core.paginator.Paginator
。page_size
- 表示一页数据条数的数值。如果设置会覆盖设置中的PAGE_SIZE
。page_query_param
- 一个字符串参数名,表示查询的页码,默认是page
。page_size_query_param
- 一个字符串参数名,表示查询的每页数据数量。默认为None
表示不能过客户端控制每页数据量。max_page_size
- 每页的最大数据量,和page_size_query_param
配合使用。
# LimitOffsetPagination
这个分页类使用了数据库查询的语法。 客户端包含一个limit
和一个offset
查询参数。limit
表示要返回的最大项数,与其他样式中的page_size
相同。offset
表示查询相对于完整的未分页项集的起始位置。
请求
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": [
…
]
}
2
3
4
5
6
7
8
9
# 使用
同分页设置一样,全局使用配置如下:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 100
}
2
3
4
也可以在GenericAPIView
的子类通过在每个视图中设置pagination_class
属性来应用分类。
# 配置
可以像上面一样复写下面的属性,来修改分类样式。
default_limit
- 一个数字值,表示客户端在查询参数中未提供limit
时所使用的值。默认值与PAGE_SIZE
设置键相同。limit_query_param
- 一个字符串,表示limit
参数的参数名,默认为limit
offset_query_param
- 一个字符串,表示offset
参数的参数名,默认为offset
max_limit
- 如果设置,这是一个数字,表示最大允许客户端请求的limit
,默认为None
# 限流
限流类似于权限,它决定是否应该授权请求。限流用于控制客户端可以向API发出的请求速率。与权限一样,可以使用多个限流。例如,对于未经身份验证的请求,你的API可能有一个严格的限流,而对于经过身份验证的请求,则不限制。
另一个可能需要使用多个节流的场景是,由于某些服务特别耗费资源,因此需要对API的不同部分施加不同的约束。
再比如,对突发访问和持续访问进行不同的限流,等等。
# 如何确定限流
与权限和身份验证一样,REST framework中的限流总是定义为一组类。
在运行视图主体之前,会检查列表中的每个限流器。如果任何限流检查失败,Throttled
异常将被引发,并且视图的主体将不会运行。
# 设置限流策略
默认的节流策略可以全局设置,使用DEFAULT_THROTTLE_CLASSES
和DEFAULT_THROTTLE_RATES
设置。
例如:
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
],
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
2
3
4
5
6
7
8
9
10
DEFAULT_THROTTLE_RATES
中使用的速率描述可以包括second
、minute
、hour
或day
作为限流周期。
也可以在在每个类视图或视图集的基础上通过throttle_classes
属性来设置限流策略。
from rest_framework.response import Response
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView
class ExampleView(APIView):
throttle_classes = [UserRateThrottle]
2
3
4
5
6
对于使用装饰器@api_view
的函数视图,可以使用如下装饰器来进行限流:
@api_view(['GET'])
@throttle_classes([UserRateThrottle])
def example_view(request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
2
3
4
5
6
7
# 内置限流器
# AnonRateThrottle
AnonRateThrottle
只会限制未经认证的用户。
允许的请求率由以下其中一个决定(按优先顺序)。
- 类上的
rate
属性,可以通过重写AnonRateThrottle
并设置该属性来提供。 DEFAULT_THROTTLE_RATES['anon']
设置
如果你想限制来自未知来源的请求的速率,AnonRateThrottle
是合适的。
# UserRateThrottle
UserRateThrottle将限制经过验证的用户在API中给定的请求速率。
允许的请求率由以下其中一个决定(按优先顺序)。
类上的
rate
属性,可以通过重写UserRateThrottle
并设置该属性来提供。DEFAULT_THROTTLE_RATES['user']
设置
一个API可以同时有多个usererratethrottles。为此,重写UserRateThrottle
并为每个类设置一个惟一的“作用域”。
例如:多个用户节流率可以通过使用以下类来实现…
class BurstRateThrottle(UserRateThrottle):
scope = 'burst'
class SustainedRateThrottle(UserRateThrottle):
scope = 'sustained'
2
3
4
5
然后设置如下
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'example.throttles.BurstRateThrottle',
'example.throttles.SustainedRateThrottle'
],
'DEFAULT_THROTTLE_RATES': {
'burst': '60/min',
'sustained': '1000/day'
}
}
2
3
4
5
6
7
8
9
10
如果您希望对每个用户进行简单的全局速率限制,那么UserRateThrottle
是合适的。
# ScopedRateThrottle
ScopedRateThrottle
类可用于限制对特定API的访问。
这个节流阀仅在被访问的视图包含.throttle_scope
属性时才会被应用。
允许的请求速率由DEFAULT_THROTTLE_RATES
设置决定。
例如,给出以下视图
class ContactListView(APIView):
throttle_scope = 'contacts'
...
class ContactDetailView(APIView):
throttle_scope = 'contacts'
...
class UploadView(APIView):
throttle_scope = 'uploads'
...
2
3
4
5
6
7
8
9
10
11
然后设置如下:
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.ScopedRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'contacts': '1000/day',
'uploads': '20/day'
}
}
2
3
4
5
6
7
8
9
用户对ContactListView
或ContactDetailView
的请求将被限制为每天1000个请求。用户对UploadView
的请求将被限制为每天20次。
本文完,感谢你的耐心阅读,如有需要可加我微信,备注「博客」并说明原因,我们一起进步,下次见。
