限流Throttling

DRF中的限流是指对API接口访问的频次进行限制,以减轻服务器压力,以防止恶意用户或者其他原因导致的API滥用。

Throttling可以根据用户的IP地址、用户名或者其他自定义的标识符来限制其访问API的频率。

限流类

DRF中提供了多种内置的限流类,可以根据不同的需求选择合适的限流方式。

常用的限流类:

类说明AnonRateThrottle根据匿名用户的IP地址进行限流。适合希望限制未知来源的请求率UserRateThrottle根据已认证用户的ID进行限流。适合希望对每个用户进行简单的全局速率限制ScopedRateThrottle用于限制对 API 特定部分的访问,如视图的访问,根据用户IP或用户ID进行限流。

设置全局默认限流策略

DRF框架默认没有进行全局限流设置,可以在配置文件中,使用DEFAULT_THROTTLE_CLASSES 和 DEFAULT_THROTTLE_RATES进行设置全局的默认限流策略。

1.针对匿名用户和认证用户分别进行限流控制

REST_FRAMEWORK = {

'DEFAULT_AUTHENTICATION_CLASSES': (

# 基本认证

'rest_framework.authentication.BasicAuthentication',

# sesssion认证

'rest_framework.authentication.SessionAuthentication',

),

'DEFAULT_PERMISSION_CLASSES': (

# 将全局权限控制方案设置为仅允许认证用户访问

'rest_framework.permissions.IsAuthenticated',

),

# 限流控制

'DEFAULT_THROTTLE_CLASSES': (

# 针对未登录(匿名)用户的限流控制类

'rest_framework.throttling.AnonRateThrottle',

# 针对登录(认证)用户的限流控制类

'rest_framework.throttling.UserRateThrottle'

),

# 指定限流频次

'DEFAULT_THROTTLE_RATES': {

# 认证用户的限流频次,一分钟内超过3此访问则出发限流

'user': '3/minute',

# 匿名用户的限流频次,一秒内超过3此访问则出发限流

'anon': '3/second',

},

}

DEFAULT_THROTTLE_RATES中使用的频率描述可选限流周期单位包括:second、minute、hour、day

2.针对匿名用户和认证用户进行统一的限流控制

'DEFAULT_THROTTLE_CLASSES': (

'rest_framework.throttling.ScopedRateThrottle',

),

限流测试:

基于类视图限流

在每个视图或每个视图集的基础上设置限流策略,通过throttle_classess属性配置限流控制类。

class TestView(ModelViewSet):

queryset = User.objects.all()

serializer_class = UserSerializer

throttle_classes = [AnonRateThrottle]

定义限流频次

可以根据实际需求定义自己的限流频次选择项

# 指定限流频次选择项

'DEFAULT_THROTTLE_RATES': {

'a': '3/minute',

'b': '2/minute'

},

使用

class TestView(ModelViewSet):

queryset = User.objects.all()

serializer_class = UserSerializer

# 针对匿名用户和认证用户进行统一的限流控制

throttle_classes = [ScopedRateThrottle]

# 指定限流频次项

throttle_scope = 'a'

自定义限流类

要自定义限流,需要创建一个继承自 BaseThrottle类的子类,并实现其中的 allow_request 和wait方法。

allow_request 方法用于判断是否允许请求通过,它接收两个参数:请求对象和视图对象。如果返回True,则说明请求被允许通过;否则返回 False,表示请求被拒绝。

wait 方法用于计算下一次请求可通过的时间,它接收三个参数:请求对象、视图对象和当前已发生的请求次数。如果返回 None,则说明请求可以立即通过;否则返回一个时间戳,表示下一次请求可通过的时间。

自定义简单限流示例:

from rest_framework.throttling import BaseThrottle

class MyCustomThrottle(BaseThrottle):

def allow_request(self, request, view):

# 在这里编写判断逻辑,返回 True 或 False

return True

def wait(self, request, view, num_requests):

# 在这里编写等待逻辑,返回 None 或下一次请求可通过的时间戳

return None

过滤Filtering

查询集过滤

class TestView(ModelViewSet):

queryset = User.objects.all().filter(name='Java')

serializer_class = UserSerializer

查询参数过滤

class TestView(ModelViewSet):

serializer_class = UserSerializer

queryset = User.objects.all()

@action(methods=['get'], detail=False)

def myFun(self, request):

query_param = request.query_params.get('name', None)

data = self.queryset.filter(name=query_param)

newData = list(data.values()) # 将查询集转换为列表

return JsonResponse(newData, safe=False) # 将数据转换为JSON格式并返回

访问:http://127.0.0.1:8000//test/myFun/?name=Vue

使用过滤器组件

Django REST framework (DRF) 提供了许多过滤器组件,用于在视图中进行过滤和排序。这些过滤器组件可以轻松地与 Django ORM 进行集成,并对查询结果进行筛选、排序和限制。

常见过滤器组件

1.DjangoFilterBackend

允许使用 Django Filter 库中的过滤器来进行高级查询。通过在视图类中设置 filter_fields 属性来指定可用的过滤字段。

2.SearchFilter

允许用户基于搜索关键字来查找特定的数据。可以通过在视图类中设置 search_fields 属性来指定可用于搜索的字段。

3.OrderingFilter:

允许用户根据选择的字段进行排序。可以通过在视图类中设置 ordering_fields 属性来指定可用于排序的字段。

4.LimitOffsetPagination:

允许将大型数据集分页显示,并允许用户针对每个页面请求特定数量的条目。

5.PageNumberPagination

与 LimitOffsetPagination 类似,但是更加常用,因为它支持按页码进行操作。

使用过滤器

django-filter库包含一个为REST framework提供高度可定制字段过滤的DjangoFilterBackend类,通过添加django-fitlter扩展来增强支持。

安装django-filter

pip install django-filter

在项目settings.py文件中注册应用:

INSTALLED_APPS = [

'django_filters',

]

1.全局使用 在settings.py文件中增加过滤后端的配置:

REST_FRAMEWORK = {

'DEFAULT_FILTER_BACKENDS': (

'django_filters.rest_framework.DjangoFilterBackend',

'rest_framework.filters.SearchFilter',

'rest_framework.filters.OrderingFilter')

}

2.局部使用 在视图函数或视图集中指定相应的过滤器类和过滤器后端

from rest_framework.filters import OrderingFilter

class TestView(ModelViewSet):

queryset = User.objects.all()

serializer_class = UserSerializer

# 指定排序类

filter_backends = [OrderingFilter]

# 指定排序字段

ordering_fields = ('id','name')

字段过滤

在视图类属性filter_backends中指定要使用的过滤器类

在视图中添加filter_fields属性,指定可以过滤的字段

from django_filters.rest_framework import DjangoFilterBackend

from rest_framework.viewsets import ModelViewSet

from user.models import User

from user.serializers import UserSerializer

class TestView(ModelViewSet):

serializer_class = UserSerializer

queryset = User.objects.all()

# filter_backends = [DjangoFilterBackend]

filterset_fields = ("name", "age")

访问:http://127.0.0.1:8000/test/

访问: http://127.0.0.1:8000/test/?age=30 访问: http://127.0.0.1:8000/test/?age=20&name=Java

字段排序

DRF提供了OrderingFilter过滤器来帮助快速指明数据按照指定字段进行排序。

DRF会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。

from rest_framework.filters import OrderingFilter

class TestView(ModelViewSet):

queryset = User.objects.all()

serializer_class = UserSerializer

# 指定排序类

filter_backends = [OrderingFilter]

# 指定排序字段

ordering_fields = ('id','name')

访问:http://127.0.0.1:8000/test/?ordering=id

访问: http://127.0.0.1:8000/test/?ordering=name

分页Pagination

在DRF中,分页类是用于处理 API 响应数据分页的工具类。DRF 提供了多个分页类可以选择使用,其中最常用的分页类为PageNumberPagination和 LimitOffsetPagination。

如果在视图内关闭分页功能,只需在视图内设置:pagination_class = None

常用分页类

1.PageNumberPagination

PageNumberPagination是基于页码来进行分页的分页类,它根据请求参数中传递的页码和每页显示的数量来返回相应的结果。

访问URL形式: http://127.0.0.1:8000/test/?page=2

可以在子类中定义的属性:

属性说明page_size每页数目page_query_param请求发送的页数关键字名,默认为"page"page_size_query_param请求发送的每页数目关键字名,默认为Nonemax_page_size请求最多能设置的每页数量

2.LimitOffsetPagination

LimitOffsetPagination 是基于偏移量和限制条目数来进行分页的分页类,它根据请求参数中传递的偏移量和限制条目数来返回相应的结果。

访问UR形式:http://127.0.0.1:8000/test/?limit=1&offset=2

可以在子类中定义的属性:

属性说明default_limit默认限制,默认值与PAGE_SIZE设置一直limit_query_param limit参数名,默认’limit’offset_query_param offset参数名,默认’offset’max_limit最大limit限制,默认None

全局与局部的使用

在配置文件中设置全局分页方式,或者在视图类中设置pagination_class属性,并指定需要使用的分页类

1.全局

REST_FRAMEWORK = {

# 指定使用的分页类

'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',

'PAGE_SIZE': 2 # 每页数量

}

访问: http://127.0.0.1:8000/test/?page=2 2.局部

from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination

class TestView(ModelViewSet):

queryset = User.objects.all()

serializer_class = UserSerializer

pagination_class = PageNumberPagination

pagination_class = LimitOffsetPagination

自定义分页类

通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_clas属性来指明。

from rest_framework.pagination import PageNumberPagination

from rest_framework.viewsets import ModelViewSet

from user.models import User

from user.serializers import UserSerializer

class MyPagination(PageNumberPagination):

page_size = 2

page_size_query_param = 'page_size'

class TestView(ModelViewSet):

queryset = User.objects.all()

serializer_class = UserSerializer

# 指定当前视图所使用的分页类

pagination_class = MyPagination

访问: http://127.0.0.1:8000/test/?page_size=3

from rest_framework.pagination import LimitOffsetPagination

class MyPagination(LimitOffsetPagination):

default_limit = 1

max_limit = 2

class TestView(ModelViewSet):

queryset = User.objects.all()

serializer_class = UserSerializer

# 指定当前视图所使用的分页类

pagination_class = MyPagination

访问:http://127.0.0.1:8000//test/?limit=2&offset=2

异常处理Exceptions

在DRF中,异常处理是通过在视图函数中捕获异常来完成的。当出现异常时,将生成一个标准响应,其中包含有关异常的详细信息。

常见异常类

DRF提供了异常处理,常见的DRF异常类如下:

异常类描述APIException所有异常的父类ValidationError当验证失败时引发的异常ParseError当无法解析请求体时引发的异常AuthenticationFailed当身份验证失败时引发的异常NotAuthenticated尚未认证引发的异常PermissionDenied当用户权限不足时引发的异常NotFound当未找到资源时引发的异常MethodNotAllowed当尝试使用不支持的HTTP方法或操作时引发的异常UnsupportedMediaType当请求使用了不受支持的媒体类型时引发的异常NotAcceptable要获取的数据格式不支持引发的异常Throttled超过限流次数引发的异常

异常处理设置

DRF框架默认使用rest_framework.views.exception_handler模块下的exception_handler函数进行异常处理。

默认异常处理设置:

REST_FRAMEWORK = {

'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'

}

自定义异常处理

可以通过定义自己的异常类来扩展这些异常,并在视图函数中捕获和处理它们。要定义自己的异常类,请从DRF中的APIException类继承,并设置status_code属性和default_detail属性

from rest_framework.exceptions import APIException

class MyException(APIException):

status_code = 400

default_detail = '自定义异常信息'

在视图函数中,您可以使用try/except块来捕获异常并返回相应的响应:

class TestView(APIView):

def get(self, request):

try:

print("do something")

1/0

except ZeroDivisionError as e:

raise MyException()

return Response({'msg': "OK"}, status=200)

urlpatterns = [

re_path(r'test/', views.TestView.as_view(), name='test'),

]

异常增强

DRF框架提供了很多异常处理函数,但有时候我们可能需要补充一些其他的异常信息处理。因此,可以在DRF框架异常处理函数的基础上,进行异常信息的增强。

from rest_framework import status

from rest_framework.response import Response

from rest_framework.views import APIView

from rest_framework.views import exception_handler as drf_exception_handler

def exception_handler(exc, context):

# 先调用DRF框架的默认异常处理函数

response = drf_exception_handler(exc, context)

if response is None:

view = context['view']

# 补充异常处理

if isinstance(exc, ZeroDivisionError):

print('[%s]: %s' % (view, type(exc)))

response = Response({'msg': '除数不能为零'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

return response

class TestView(APIView):

def get(self, request):

1 / 0

return Response({'msg': "OK"}, status=200)

在配置文件中声明自定义的异常处理:

REST_FRAMEWORK = {

'EXCEPTION_HANDLER': 'user.utils.exceptions.exception_handler'

}

---------------------------END---------------------------

题外话

感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。

CSDN大礼包:全网最全《Python学习资料》免费赠送!(安全链接,放心点击)

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。

二、Python兼职渠道推荐*

学的同时助你创收,每天花1-2小时兼职,轻松稿定生活费.

三、最新Python学习笔记

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

四、实战案例

纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

CSDN大礼包:全网最全《Python学习资料》免费赠送!(安全链接,放心点击)

若有侵权,请联系删除

推荐文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。