likes
comments
collection
share

Django REST Framework(DRF)框架之其他常用API的使用

作者站长头像
站长
· 阅读数 13

限流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',
),

限流测试: Django REST Framework(DRF)框架之其他常用API的使用

基于类视图限流

在每个视图或每个视图集的基础上设置限流策略,通过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

Django REST Framework(DRF)框架之其他常用API的使用

查询参数过滤

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/ Django REST Framework(DRF)框架之其他常用API的使用

访问: http://127.0.0.1:8000/test/?age=30 Django REST Framework(DRF)框架之其他常用API的使用 访问: http://127.0.0.1:8000/test/?age=20&name=Java Django REST Framework(DRF)框架之其他常用API的使用

字段排序

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 Django REST Framework(DRF)框架之其他常用API的使用

访问: http://127.0.0.1:8000/test/?ordering=name Django REST Framework(DRF)框架之其他常用API的使用

分页Pagination

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

如果在视图内关闭分页功能,只需在视图内设置: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请求发送的每页数目关键字名,默认为None
max_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 Django REST Framework(DRF)框架之其他常用API的使用 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 Django REST Framework(DRF)框架之其他常用API的使用

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 Django REST Framework(DRF)框架之其他常用API的使用

异常处理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'),
]

Django REST Framework(DRF)框架之其他常用API的使用

异常增强

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'
}

Django REST Framework(DRF)框架之其他常用API的使用