DRF框架基本组件之频率&解析器&分页

频率控制

限制类似于权限,因为它确定是否应该授权请求。Throttles表示临时状态,用于控制客户端可以对API发出的请求的速率。

与权限一样,可以使用多个限制。您的API可能对未经身份验证的请求具有限制性限制,并且对经过身份验证的请求限制较少。

您可能希望使用多个限制的另一种情况是,如果您需要对API的不同部分施加不同的约束,因为某些服务特别是资源密集型。

如果要同时施加突发限制速率和持续限制速率,也可以使用多个限制。例如,您可能希望将用户限制为每分钟最多60个请求,每天1000个请求。

Throttles不一定仅涉及限速请求。例如,存储服务可能还需要对带宽进行限制,并且付费数据服务可能希望对正在访问的特定数量的记录进行限制。

如何确定节流量

与权限和身份验证一样,REST框架中的限制始终定义为类列表。

在运行视图的主体之前,检查列表中的每个节流阀。如果任何油门检查失败,exceptions.Throttled将引发异常,并且视图的主体将不会运行。

设置限制策略

可以使用DEFAULT_THROTTLE_CLASSESDEFAULT_THROTTLE_RATES设置全局设置默认限制策略例如。

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '100/day',
        'user': '1000/day'
    }
}

用在速率的描述DEFAULT_THROTTLE_RATES可以包括secondminutehourday作为节流段。

您还可以使用APIView基于类的视图在每个视图或每个视图集的基础上设置限制策略

from rest_framework.response import Response
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView

class ExampleView(APIView):
    throttle_classes = (UserRateThrottle,)

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)

 

或者,如果您正在使用@api_view具有基于功能的视图装饰器。

@api_view(['GET'])
@throttle_classes([UserRateThrottle])
def example_view(request, format=None):
    content = {
        'status': 'request was permitted'
    }
    return Response(content)

设置自定义的频率控制器

在app01.service.throttles.py中:

from rest_framework.throttling import BaseThrottle

VISIT_RECORD={}
class VisitThrottle(BaseThrottle):

    def __init__(self):
        self.history=None

    def allow_request(self,request,view):
        remote_addr = request.META.get('REMOTE_ADDR')
        print(remote_addr)
        import time
        ctime=time.time()

        if remote_addr not in VISIT_RECORD:
            VISIT_RECORD[remote_addr]=[ctime,]
            return True

        history=VISIT_RECORD.get(remote_addr)
        self.history=history

        while history and history[-1]<ctime-60:
            history.pop()

        if len(history)<3:
            history.insert(0,ctime)
            return True
        else:
            return False

    def wait(self):
        import time
        ctime=time.time()
        return 60-(ctime-self.history[-1])

在views.py中:

from app01.service.throttles import *

class BookViewSet(generics.ListCreateAPIView):
    throttle_classes = [VisitThrottle,]
    queryset = Book.objects.all()
    serializer_class = BookSerializers

全局视图throttle

REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
    "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
    "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",]
}

内置throttle类

在app01.service.throttles.py修改为:

class VisitThrottle(SimpleRateThrottle):

    scope="visit_rate"
    def get_cache_key(self, request, view):

        return self.get_ident(request)

settings.py设置:

REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
    "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
    "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",],
    "DEFAULT_THROTTLE_RATES":{
        "visit_rate":"5/m",
    }
}

REST 框架包括一些内置的Parser类,允许你接受各种媒体类型的请求。还支持定义自己的自定义解析器,这使你可以灵活地设计API接受的媒体类型。

解析器如何确定

一组视图的有效解析器总是被定义为一个类的列表。当访问request.data时,REST框架将检查传入请求中的Content-Type头,并确定用于解析请求内容的解析器。


注意: 开发客户端应用程序时应该始终记住在HTTP请求中发送数据时确保设置Content-Type头。

如果你不设置内容类型,大多数客户端将默认使用'application/x-www-form-urlencoded',而这可能并不是你想要的。

举个例子,如果你使用jQuery的.ajax() 方法发送json编码数据,你应该确保包含contentType:'application / json'设置。


设置解析器

可以使用DEFAULT_PARSER_CLASSES设置全局默认的解析器集。例如,以下设置将仅允许具有JSON内容的请求,而不是JSON或表单数据的默认值。

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
    )
}

 

你还可以设置用于单个视图或视图集的解析器, 使用APIView类视图。

from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    """
    可以接收JSON内容POST请求的视图。
    """
    parser_classes = (JSONParser,)

    def post(self, request, format=None):
        return Response({'received data': request.data})

 

或者,如果你使用基于方法的视图的@api_view装饰器。

from rest_framework.decorators import api_view
from rest_framework.decorators import parser_classes

@api_view(['POST'])
@parser_classes((JSONParser,))
def example_view(request, format=None):
    """
    可以接收JSON内容POST请求的视图
    """
    return Response({'received data': request.data})

 

分页

 

REST框架包括对可自定义分页样式的支持。这允许您修改将大型结果集拆分为单个数据页的方式。

分页API可以支持:

  • 分页链接是作为响应内容的一部分提供的。
  • 响应标头中包含的分页链接,例如Content-RangeLink

内置样式目前都使用包含在响应内容中的链接。使用可浏览API时,此样式更易于访问。

只有在使用通用视图或视图集时,才会自动执行分页。如果您使用常规APIView需要自己调用分页API以确保返回分页响应。有关示例,请参阅mixins.ListModelMixingenerics.GenericAPIView的源代码

可以通过将分页类设置为关闭分页None

设置分页样式

可以使用DEFAULT_PAGINATION_CLASSPAGE_SIZE设置键全局设置默认分页样式例如,要使用内置限制/偏移分页,您可以执行以下操作:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 100
}

 

请注意,您需要设置分页类和应该使用的页面大小。

您还可以使用该pagination_class属性在单个视图上设置分页类通常,您希望在整个API中使用相同的分页样式,尽管您可能希望基于每个视图改变分页的各个方面,例如默认或最大页面大小。

修改分页样式

如果要修改分页样式的特定方面,则需要覆盖其中一个分页类,并设置要更改的属性。

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

 

或者使用DEFAULT_PAGINATION_CLASS设置键全局应用样式例如:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'
}

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": [
       
    ]
}

使用:

PageNumberPagination全局启用该样式,请使用以下配置,PAGE_SIZE根据需要进行修改

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 100
}

 

GenericAPIView子类上,您还可以将pagination_class属性设置为PageNumberPagination基于每个视图进行选择。

所述PageNumberPagination类包括多个可重写修改分页样式属性。

要设置这些属性,您应该覆盖PageNumberPagination该类,然后启用上面的自定义分页类。

  • django_paginator_class - 要使用的Django Paginator类。默认值是django.core.paginator.Paginator,对于大多数用例来说应该没问题。
  • page_size - 表示页面大小的数值。如果设置,则会覆盖该PAGE_SIZE设置。默认值与PAGE_SIZE设置键的值相同
  • page_query_param - 一个字符串值,指示用于分页控件的查询参数的名称。
  • page_size_query_param - 如果设置,这是一个字符串值,指示允许客户端基于每个请求设置页面大小的查询参数的名称。默认为None,表示客户端可能无法控制请求的页面大小。
  • max_page_size - 如果设置,这是一个数值,表示允许的最大请求页面大小。此属性仅在page_size_query_param设置时有效
  • last_page_strings- 字符串值的列表或元组,指示可用于page_query_param请求集合中最后一页的值。默认为('last',)
  • template - 在可浏览API中呈现分页控件时要使用的模板的名称。可以重写以修改呈现样式,或设置为None完全禁用HTML分页控件。默认为"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": [
       
    ]
}

使用

LimitOffsetPagination全局启用该样式,请使用以下配置:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
}

 

您也可以选择设置PAGE_SIZE密钥。如果PAGE_SIZE还使用参数,则limit查询参数将是可选的,并且客户端可以省略该参数。

GenericAPIView子类上,您还可以将pagination_class属性设置为LimitOffsetPagination基于每个视图进行选择。

组态

所述LimitOffsetPagination类包括多个可重写修改分页样式属性。

要设置这些属性,您应该覆盖LimitOffsetPagination该类,然后启用上面的自定义分页类。

  • default_limit - 一个数值,指示客户端在查询参数中未提供限制时使用的限制。默认值与PAGE_SIZE设置键的值相同
  • limit_query_param - 表示“limit”查询参数名称的字符串值。默认为'limit'
  • offset_query_param - 表示“偏移”查询参数名称的字符串值。默认为'offset'
  • max_limit - 如果设置,则这是一个数值,表示客户端可能请求的最大允许限制。默认为None
  • template - 在可浏览API中呈现分页控件时要使用的模板的名称。可以重写以修改呈现样式,或设置为None完全禁用HTML分页控件。默认为"rest_framework/pagination/numbers.html"

 

posted on 2019-06-16 15:56  Orvis  阅读(156)  评论(0编辑  收藏  举报

导航