DRF学习

DRF

安装

  • pip install djangorestframework

注册

  • 在settings.py中进行注册

    INSTALLED_APPS = [
        ...
        'rest_framework',
    ]
    

DRF简单使用

models模型数据

from django.db import models
from django.contrib.auth.models import User


class Merchant(models.Model):
    """
    商家
    """
    name = models.CharField(max_length=200, verbose_name='商家名称', null=False)
    address = models.CharField(max_length=200, verbose_name='商家', null=False)
    logo = models.CharField(max_length=200, verbose_name='商家logo', null=False)
    notice = models.CharField(max_length=200, verbose_name='商家的公告', null=True, blank=True)
    up_send = models.DecimalField(verbose_name='起送价', default=0, max_digits=6, decimal_places=2)
    lon = models.FloatField(verbose_name='经度')
    lat = models.FloatField(verbose_name='纬度')

    creater = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)


class GoodsCategory(models.Model):
    """
    商家商品分类
    """
    name = models.CharField(max_length=20, verbose_name='分类名称')
    merchant = models.ForeignKey(Merchant, on_delete=models.CASCADE, verbose_name='所属商家', related_name='categories')


class Goods(models.Model):
    """
    商品
    """
    name = models.CharField(max_length=200, verbose_name='商品名称')
    picture = models.CharField(max_length=200, verbose_name='商品图片')
    intro = models.CharField(max_length=200)
    price = models.DecimalField(verbose_name='商品价格', max_digits=6, decimal_places=2)  # 最多6位数,2位小数。9999.99
    category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, related_name='goods_list')

  • 模型和下面的文件并不在一个目录下
  • 下面的可以手动创建一个目录,添加python文件直接写代码即可

序列化字段 serializers.py

from rest_framework import serializers
from meituan.models import Merchant


class MerchantSerializers(serializers.ModelSerializer):
    class Meta:
        model = Merchant
        # 需要序列化的字段
        fields = "__all__"
        # exclude = ['name']

编写视图函数 views.py

from rest_framework import viewsets
from meituan.models import Merchant
from .serializers import MerchantSerializers


# 这个视图已经包含了CRUD
class MerchantViewset(viewsets.ModelViewSet):
    queryset = Merchant.objects.all()
    serializer_class = MerchantSerializers

映射路径 urls.py

from rest_framework.routers import DefaultRouter
from .views import MerchantViewset

router = DefaultRouter()
router.register('merchant', MerchantViewset, basename='merchant')

app_name = 'quickstart'

urlpatterns = [] + router.urls

序列化

  • drf中的序列化主要是用来将模型序列化成JSON格式的对象。但是除了序列化,他还具有表单验证功能,数据存储和更新功能

非模板序列化

  • 继承与 serializers.Serializer

  • 自定义需要序列化的字段,可以重写更新,添加数据的方法

    # 序列化字段(非模板序列化)
    class MerchantSerializer(serializers.Serializer):
        id = serializers.IntegerField(read_only=True)
        name = serializers.CharField(max_length=200, required=True, error_messages={"required": "name字段是必填的!"})
        address = serializers.CharField(max_length=200, required=True)
        notice = serializers.CharField(max_length=200, required=False)
        logo = serializers.CharField(max_length=200)
        up_send = serializers.DecimalField(required=False, max_digits=6, decimal_places=2)
        lon = serializers.FloatField(required=True)
        lat = serializers.FloatField(required=True)
    
        def create(self, validated_data):
            # 创建数据
            # validated_data是一个字段,比如{"name": "sixu"}
            # 但是create需要传入的是关键字参数,加上两个星号就可以将name转为关键字参数
            # eg:   {"name": "sixu"}   ===>   name="sixu"
            return Merchant.objects.create(**validated_data)
    
        def update(self, instance, validated_data):
            # 修改数据之前我要拿到数据,如果没有数据就用之前的数据
            instance.name = validated_data.get("name", instance.name)
            instance.address = validated_data.get("address", instance.address)
            instance.notice = validated_data.get("notice", instance.notice)
            instance.logo = validated_data.get("logo", instance.logo)
            instance.up_send = validated_data.get("up_send", instance.up_send)
            instance.lon = validated_data.get("lon", instance.lon)
            instance.lat = validated_data.get("lat", instance.lat)
            # 保存修改
            instance.save()
            # 返回数据
            return instance
    

模板序列化

  • 也可以自定义需要序列化的字段,但是不用这个麻烦

  • 继承与 serializers.ModelSerializer

    • fields 指定序列化的字段
    • exclude 指定不参与序列化的字段
    # 使用模板序列化
    class MerchantSerializer(serializers.ModelSerializer):
        class Meta:
            # 导入models模型中的类
            model = Merchants
            # 序列化所有字段,也可以序列化指定字段(属性)  比如:  fields = ['name','xxx']
            fields = "__all__"
            # 可以指定那些字段(属性)不进行序列化
            # exclude = ['name','age']
    

对个别字段进行验证

  • validated_data:可对想要进行验证的属性进行验证

  • validated:可以对全部的属性进行验证

    class GoodsCategorySerializer(serializers.ModelSerializer):
        merchant = MerchantSerializer(read_only=True)
        goods_list = GoodSerializer(read_only=True, many=True)
        merchant_id = serializers.IntegerField(write_only=True)
        class Meta:
            model = GoodsCategory
            fields = "__all__"
    
        # 验证merchant_id是否存在
        def validated_merchant_id(self, value):
            if not Merchant.objects.get(pk=value).exists():
                raise serializers.ValidationError("商家不存在!")
            return value
        
        def create(self, validated_data):
            merchant_id = validated_data.get("merchant_id")
            merchant = Merchant.objects.get(pk=merchant_id)
            return GoodsCategory.objects.create(**validated_data, merchant=merchant)
    

序列化的嵌套

  • 有时候在一个序列化中,我们可能需要其他模型的序列化。这时候就可以使用到序列化的嵌套

  • 比如我们在GoodsCategory中想要获取Merchant以及这个分类下的商品Goods

    class GoodsCategorySerializer(serializers.ModelSerializer):
        # 序列化的嵌套获取商家的详细信息
        merchant = MerchantSerializer(read_only=True)
        # 获取商品分类的详细信息, 必须是  xxxx_list
        goods_list = GoodSerializer(read_only=True, many=True)
        # 发送请求时传入的商家id
        merchant_id = serializers.IntegerField(write_only=True)
    
        class Meta:
            model = GoodsCategory
            fields = "__all__"
    
        # 验证merchant_id是否存在
        def validated_merchant_id(self, value):
            if not Merchant.objects.get(pk=value).exists():
                raise serializers.ValidationError("商家不存在!")
            return value
    
        def create(self, validated_data):
            merchant_id = validated_data.get("merchant_id")
            merchant = Merchant.objects.get(pk=merchant_id)
            return GoodsCategory.objects.create(**validated_data, merchant=merchant)
    

视图函数的使用

  • 可以在视图函数中拿到由序列化验证之后的数据

    # 使用Response这函数要引入
    from rest_framework.response import Response
    from rest_framework.decorators import api_view
    
    from .serializers import MerchantSerializer, GoodsCategorySerializer
    from django.http import JsonResponse
    from meituan.models import Merchant, GoodsCategory, Goods
    
    @api_view(['GET', 'POST'])
    def merchant(request):
        if request.method == "GET":
            # 获取数据
            queryset = Merchant.objects.all()
            # 序列化数据
            
            # instance需要传递一个ORM对象或者是queryset对象,将orm模型序列化为JSON
            # many: 拿到的是多个而不是一个
            serializer = MerchantSerializer(instance=queryset, many=True)
            
            # serializer 可以理解为是一个列表,里面存放的是一个个序列化对象, 类型是:rest_framework.serializers.ListSerializer
            print(serializer, type(serializer))
            
            # serializer.data返回的数据格式是:[{},{}...]   类型是:rest_framework.utils.serializer_helpers.ReturnList
            print(serializer.data, type(serializer.data))
            
            # 返回数据使用JsonResponse
            # return JsonResponse(serializer.data, status=200, safe=False)
            return Response(serializer.data, status=200)
        else:
            # 获取数据
            serializer = MerchantSerializer(data=request.POST)
            # 验证数据
            if serializer.is_valid():
                # 保存数据
                serializer.save()
                # 返回成功信息
                return JsonResponse(serializer.data, status=200)
            else:
                # 返回失败信息
                return JsonResponse(serializer.errors, status=400)
    

read_only 和 write_only

  • read_only=True:这个字段只只能读,只有在返回数据的时候会使用
  • write_only=True:这个字段只能被写,只有在新增数据或者更新数据的时候会用到

验证

验证用户上传上来的字段是否满足要求。可以通过以下三种方式来实现。

  1. 验证在Field中通过参数的形式进行指定。比如required等。
  2. 通过重写validate(self,attrs)方法进行验证。attrs中包含了所有字段。如果验证不通过,那么调用raise serializer.ValidationError('error')即可。
  3. 重写validate_字段名(self,value)方法进行验证。这个是针对某个字段进行验证的。如果验证不通过,也可以抛出异常。

请求和响应

Request和Response对象

Requeset

  • request.POST:只能处理表单数据,获取通过POST方式上传上来的数据
  • request.data:以处理任意的数据。可以获取通过POSTPUTPATCH等方式上传上来的数据
  • request.query_params:查询参数

Response

  • Response 可以自动的根据返回的数据类型来决定返回什么样的格式。并且会自动的监听如果是浏览器访问,那么会返回这个路由的信息

状态码

from rest_framework import status

# 这个类中有已经写好的状态码可供使用
比如:
HTTP_200_OK = 200
HTTP_201_CREATED = 201
HTTP_202_ACCEPTED = 202
HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203
HTTP_204_NO_CONTENT = 204
HTTP_205_RESET_CONTENT = 205
HTTP_206_PARTIAL_CONTENT = 206
HTTP_207_MULTI_STATUS = 207

使用Request和Response

  • Request和Response 都只能在 DRF 的 APIView 中才能使用

  • 引入 rest_framework.decorators.api_view 装饰

    from rest_framework.decorators import api_view
    
    @api_view(['GET', 'PUT', 'DELETE'])
    def snippet_detail(request, pk):
        """
        Retrieve, update or delete a code snippet.
        """
        try:
            snippet = Snippet.objects.get(pk=pk)
        except Snippet.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
    
        if request.method == 'GET':
            serializer = SnippetSerializer(snippet)
            return Response(serializer.data)
    
        elif request.method == 'PUT':
            serializer = SnippetSerializer(snippet, data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
        elif request.method == 'DELETE':
            snippet.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
    
  • 如果是类视图,那么可以让你的类继承自 rest_framework.views.APIView

    from rest_framework.views import APIView
    
    class MerchantView(APIView):
        def get(self,request):
            return Response("你好")
    

类视图

APIView

  • APIView是DRF中类视图最基本的父类。基本用法跟Django中自带的View类是一样的。也是自己分别实现get、post等方法
  • APIView中还继承了一些常用的属性,比如authentication_classes、permission_classes、throttle_classes
from rest_framework.views import APIView
from meituan.models import Merchant
from django.http import Http404
from rest_framework import status
from .serializers import MerchantSerializer
from rest_framework.response import Response


# 使用APIView的写法
class MerchantView(APIView):
    """
    检索, 更新和删除一个merchant实例对象.
    """

    def get_object(self, pk):
        try:
            return Merchant.objects.get(pk=pk)
        except Merchant.DoesNotExist:
            raise Http404


    def get(self, request, pk=None):
        if pk:
            merchant = self.get_object(pk)
            serializer = MerchantSerializer(merchant)
            return Response(serializer.data)
        else:
            queryset = Merchant.objects.all()
            serializer = MerchantSerializer(instance=queryset, many=True)
            return Response(serializer.data)

    def put(self, request, pk):
        merchant = self.get_object(pk)
        serializer = MerchantSerializer(merchant, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        merchant = self.get_object(pk)
        merchant.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

minix

  • mixins翻译成中文是混入,组件的意思。在DRF中,针对获取列表,检索,创建等操作,都有相应的mixin
from meituan.models import Merchant
from .serializers import MerchantSerializer
from rest_framework import generics
from rest_framework import mixins

class MerchantView(
    generics.GenericAPIView,
    mixins.ListModelMixin,
    mixins.RetrieveModelMixin,
    mixins.CreateModelMixin,
    mixins.UpdateModelMixin,
    mixins.DestroyModelMixin
):
    queryset = Merchant.objects.all()
    serializer_class = MerchantSerializer

    def get(self, request, pk=None):
        if pk:
            # 如果有pk参数就查一条
            return self.retrieve(request)
        else:
            # 否则查所有
            return self.list(request)

    # 重写perform_create这个方法可以写自己的保存逻辑
    # def perform_create(self, serializer):
    #     # 比如说将当前用户添加到数据中
    #     serializer.save(created=self.request.user)

    # 添加数据
    def post(self, request):
        return self.create(request)

    # 修改数据
    def put(self, request, pk):
        return self.update(request, pk)

    # 删除数据
    def delete(self, request, pk):
        return self.destroy(request, pk)

Generic写法

  • 针对这些mixin,DRF还进一步的进行了封装,放到generics下
    • generics.ListAPIView:实现获取列表的。实现get方法。
    • generics.CreateAPIView:实现创建数据的。实现post方法。
    • generics.UpdateAPIView:实现更新数据的。实现put方法。
    • generics.DestroyAPIView:实现删除数据的。实现delete方法。
    • generics.RetrieveAPIView:实现检索数据的。
    • generics.ListCreateAPIView:实现列表和创建数据的。
    • generics.RetrieveUpdateAPIView:实现检索和更新数据的。
    • generics.RetrieveDestroyAPIView:实现检索和删除数据的。
    • generics.RetrieveUpdateDestroyAPIView:实现检索和更新和删除数据的。
from meituan.models import Merchant
from .serializers import MerchantSerializer
from rest_framework import generics

# 使用Generic的写法(通用视图)
class MerchantView(
    generics.ListAPIView,
    generics.CreateAPIView,
    generics.UpdateAPIView,
    generics.DestroyAPIView
    # RetrieveAPIView   和   ListAPIView   不能共用
    # generics.RetrieveAPIView
):
    queryset = Merchant.objects.all()
    serializer_class = MerchantSerializer


# 如果想在通用视图下共用  RetrieveAPIView   和   ListAPIView
# 则需要重新写要要给类视图于另一个做区分
# 需要在映射路径中重新定义一个路径
class MerchantOneView(generics.RetrieveAPIView):
    queryset = Merchant.objects.all()
    serializer_class = MerchantSerializer
    # 设置检索的字段
    # lookup_field = 'name'
    # 修改这个字段在url中显示的key,不修改的话默认是  lookup_field 的值
    # 如果有多个的话,好像会报错
    # lookup_url_kwarg = "pk"
  • 视图的写法

    urlpatterns = [
        path('merchant/',views.MerchantView.as_view()),
        path('merchant/<int:pk>/',views.MerchantView.as_view())
    ]
    
  • url和method产生的结果

    method url 结果
    get /merchant/31/ 获取id=31的merchant数据
    post /merchant/ 添加新的merchant数据
    put /merchant/31/ 修改id=31的merchant数据
    delete /merchant/31 删除id=31的merchant数据
  • 因为这里retrieve占用了get方法,所以如果想要实现获取列表的功能,那么需要再重新定义一个url和视图

  • 这也是为什么List和Retrieve不能同时存在一个视图中的原因

    # views.py
    class MerchantListView(generics.ListAPIView,):
        serializer_class = MerchantSerializer
        queryset = Merchant.objects.all()
    
    # urls.py
    urlpatterns = [
        path('merchant/',views.MerchantView.as_view()),
        path('merchant/<int:pk>/',views.MerchantView.as_view()),
        path('merchants/',views.MerchantListView.as_view())
        ...
    ]
    

视图集

  • 在视图函数中继承 viewsets.ModelViewSet

    from rest_framework import viewsets
    
    # 使用视图集的方式
    class MerchantViewSet(viewsets.ModelViewSet):
        queryset = Merchant.objects.all()
        serializer_class = MerchantSerializer
    
  • 在urls中注册路由

    from rest_framework.routers import DefaultRouter
    
    router = DefaultRouter()
    router.register("merchant",MerchantViewSet,basename="merchant")
    
    urlpatterns = []+router.urls
    
  • 在视图集中添加 url

    from rest_framework.decorators import action
    
    class MerchantViewSet(viewsets.ModelViewSet):
        queryset = Merchant.objects.all()
        serializer_class = MerchantSerializer
    
        # url_path可以设置这个路径的url,默认的url路径是方法名
        @action(['GET'],detail=False, url_path='cs')
        def changsha(self,request,*args,**kwargs):
            queryset = self.get_queryset()
            queryset = queryset.filter(name__contains="长沙")
            serializer = MerchantSerializer(queryset,many=True)
            return Response(serializer.data)
    

权限验证

BasicAuthentication

JWT

  • 安装pyjwt
    • pip install pyjwt

获取 jwt_token 和 解析 jwt_token

import jwt
import time

def get_jwt_token(userid):
    # 设置过期时间
    timestamp = int(time.time() * 60*60)
    # 设置加密密钥
    key = 'sixu'
    # algorithm是加密方式,默认是HS256
    token = jwt.encode({"userid": userid, "exp": timestamp}, key=key, algorithm='HS256')
    return token

# 解析jwt_token
def get_jwt_payload():
    # 获取token
    token = get_jwt_token(1)
    # 解析token
    jwt_payload = jwt.decode(token, key='sixu', algorithms=['HS256'])
    return jwt_payload

# 验证获取token
token = get_jwt_token(1)
print("token:", token)

# 验证解析token
ss = get_jwt_payload()
print(ss.get("userid"))

在django里使用 jwt_token

  • 写一个类进行获取和解析

    import jwt
    import time
    from django.conf import settings
    from rest_framework.authentication import BaseAuthentication, get_authorization_header
    from rest_framework import exceptions
    from django.contrib.auth import get_user_model
    
    User = get_user_model()
    
    # 生成jwt的token函数
    def generate_jwt(user):
        # 设置过期时间为7天后
        timestamp = int(time.time() + 60*60*24*7)
        # 测试token过期
        # timestamp = int(time.time() + 2)
        # 获取token  key是加密的密钥
        # exp是过期时间,必须是这个名字
        token = jwt.encode({"userId": user.id, "exp": timestamp}, key=settings.SECRET_KEY, algorithm='HS256')
        return token
    
    
    class JWTAuthentication(BaseAuthentication):
        """
        Authorization: JWT 401f7ac837da42b97f613d789819ff93537bee6a
        """
        keyword = 'JWT'
        model = None
    
        def authenticate(self, request):
            # 获取请求头中的数据,获取的是编码后的数据
            auth = get_authorization_header(request).split()
            # 分割后auth应该是这个样子的
            # auth ===> ['JWT','xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx']
    
            # 先与 keyword 进行对比,如果不想等直接返回None(验证失败)
            if not auth or auth[0].lower() != self.keyword.lower().encode():
                return None
    
            if len(auth) == 1:
                msg = '没有JWT的值'
                raise exceptions.AuthenticationFailed(msg)
            elif len(auth) > 2:
                msg = '无效的token'
                raise exceptions.AuthenticationFailed(msg)
            try:
                # 对token进行解码   auth分割后下标为1的元素是token
                jwt_token = auth[1]
                payload = jwt.decode(jwt_token, key=settings.SECRET_KEY, algorithms='HS256')
                userId = payload.get("userId")
                try:
                    user = User.objects.get(id=userId)
                    return user, jwt_token
                except Exception:
                    msg = '无效的token'
                    raise exceptions.AuthenticationFailed(msg)
            except UnicodeError:
                msg = '编码存在问题'
                raise exceptions.AuthenticationFailed(msg)
            except jwt.ExpiredSignatureError:
                msg = 'token已过期'
                raise exceptions.AuthenticationFailed(msg)
    
  • 在视图函数中调用这个工具类生成token

    from meituan.models import Merchant
    from rest_framework.decorators import api_view
    from rest_framework.response import Response
    
    from .serializers import MerchantSerializer
    from rest_framework import viewsets
    from rest_framework.permissions import IsAuthenticated
    from .authentications import generate_jwt, JWTAuthentication
    
    # 获取django自带的的user对象
    from django.contrib.auth import get_user_model
    
    User = get_user_model()
    
    
    # 使用视图集的方式
    class MerchantViewSet(viewsets.ModelViewSet):
        queryset = Merchant.objects.all()
        serializer_class = MerchantSerializer
    
        # authentication_classes: 判断用户是否已经登录
        authentication_classes = [JWTAuthentication]
        # permission_classes: 根据用户的权限进行限制访问
        permission_classes = [IsAuthenticated]
    
        # 配置上面的两行代码之后
        # 在进行请求的时候就需要进行验证
        # 在请求的请求头中添加以下信息
        # AUTHORIZATION    basic c2l4dToxMjM0NTY=    // 这种格式就是验证的格式  AUTHORIZATION  是请求头中的key.  basic c2l4dToxMjM0NTY=   是key的value,注意用空格隔开
        # c2l4dToxMjM0NTY=  是怎么来的呢
        # 1. 导入base64的包
        # 2. base64.b64encode(b'sixu:123456') 进行编码  sixu:123456,是管理员的账号和密码用冒号分开
    
    
    
    # 调用这个视图函数就会返回一个jwt_token
    @api_view(['GET'])
    def token_view(request):
        token = generate_jwt(User.objects.get(id__contains=2))
        return Response({'token': token})
    
  • 在urls.py文件中进行映射

    from django.urls import path
    from .views import MerchantViewSet, token_view
    from rest_framework.routers import DefaultRouter
    
    app_name = "authpermission"
    router = DefaultRouter()
    router.register('merchant', MerchantViewSet, basename='merchant')
    
    urlpatterns = [
        path('token/', token_view, name='token')
    
    ] + router.urls
    
    

自定义权限

  • 写一个自定义权限类

    • authentications.py

      # 自定义权限
      from rest_framework import permissions
      
      
      class PermissionsDemo(permissions.BasePermission):
      
          # 第一次限制(小区门卫)
          def has_permission(self, request, view):
              # 发送请求的时候在请求头中设置 referer,  值任意输   用来测试
              if request.META.get('HTTP_REFERER'):
                  return True
              return False
      
          # 第二次限制(单元楼)
          def has_object_permission(self, request, view, obj):
              if '长沙' in obj.name:
                  return True
              return False
      
      
  • 在视图函数中添加 permission_classes 用来启用自定义权限

    from meituan.models import Merchant
    from rest_framework.decorators import api_view
    from rest_framework.response import Response
    
    from .serializers import MerchantSerializer
    from rest_framework import viewsets
    from rest_framework.authentication import BasicAuthentication
    from rest_framework.permissions import IsAuthenticated, IsAdminUser
    from .authentications import generate_jwt, JWTAuthentication
    # 导入自定义权限包
    from .pemissions import PermissionsDemo
    
    # 获取django自带的的user对象
    from django.contrib.auth import get_user_model
    
    class MerchantViewSet(viewsets.ModelViewSet):
        queryset = Merchant.objects.all()
        serializer_class = MerchantSerializer
    
        # authentication_classes: 判断用户是否已经登录, 根据那种方式进行判断
        authentication_classes = [JWTAuthentication, BasicAuthentication]
        # permission_classes: 根据用户的权限进行限制访问,
        # IsAuthenticated: 用户登陆的才可以访问
        # IsAdminUser: 管理员才可以访问
        # permission_classes = [IsAuthenticated, IsAdminUser]
    	
        # 自定义权限的使用,别忘导包,这个是在这个视图进行限制,可以在settings.py中对所有视图进行限制
        permission_classes = [PermissionsDemo]
    

限速节流

  • 通过限制访问的次数和频率来限制行为
  • 限速节流的配置分为两种,第一种是在settings.REST_FRAMEWORK中进行设置,第二种是针对每个视图函数进行配置
  • 限度的单位有 second/minute/hour/day

全局配置

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
        # 对匿名用户
        'rest_framework.throttling.AnonRateThrottle',
        # 对登陆用户
        'rest_framework.throttling.UserRateThrottle'
    ],
    'DEFAULT_THROTTLE_RATES': {
        # 一天访问2次
        'anon': '2/day',
        # 一天访问3次
        'user': '3/day'
    }
}

视图配置

  • 可以只针对某个视图进行限速节流

  • views.py

    class MerchantViewSet(viewsets.ModelViewSet):
        queryset = Merchant.objects.all()
        serializer_class = MerchantSerializer
    
        # 自定义限速节流
        throttle_scope = 'merchant'
    
  • 在settings.py文件中进行其中

    REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_CLASSES': [
            # 自定义限速节流
            'rest_framework.throttling.ScopedRateThrottle'
        ],
        'DEFAULT_THROTTLE_RATES': {
            # 自定义次数
            'merchant': '2/day'
        }
    }
    

分页

异常

posted @ 2024-08-05 17:54  愿风带走思绪  阅读(66)  评论(0)    收藏  举报