Django限流与Mixin的使用

14 篇文章 1 订阅
10 篇文章 1 订阅

一级类视图

APIView
from rest_framework.views import APIView

APIView是REST framework提供的所有视图的基类,继承自Django的View父类。

APIViewView的不同之处在于:

  • 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
  • 视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
  • 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。

支持定义的属性:

  • authentication_classes列表或元祖,身份认证类
  • permissoin_classes列表或元祖,权限检查类
  • throttle_classes列表或元祖,流量控制类

APIView中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。

class Test(APIView):
    """
    APIView演示
    """
    def get(self,request):
        test_obj = Test.objects.all()
        ser = Test_Serializer(test_obj,many=True)
        return Response(ser.data)
    
    def post(self,request):
        ser = Test_Serializer(data=request.data)
        if ser.is_valid():
            ser.save()
        return Response({"code":200})
限流配制

对接口访问的频次进行限制,以减轻服务器压力

全局配制

# settings.py

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '2/m', # 匿名用户对应的节流次数
        'user': '5/m' # 登录用户对应的节流次数
    }
}

DEFAULT_THROTTLE_RATES可以使用second,minute,hourday来指明周期,也可以在具体视图中通过throttle_classess属性来配置

# 对需要限流的接口进行设置
from rest_framework.throttling import UserRateThrottle

class Test(APIView):
    throttle_classes = (UserRateThrottle,)
    
    def get(self,request):
        pass

可选限流类

1) AnonRateThrottle限制所有匿名未认证用户,使用IP区分用户。

使用DEFAULT_THROTTLE_RATES['anon']来设置频次

2)UserRateThrottle限制认证用户,使用user id 来区分。

使用DEFAULT_THROTTLE_RATES['user']来这是频次

3)ScopedRateThrottle限制用户对于每个视图的访问频次,使用ip或user id。

二级视图

GenericAPIView

继承自APIVIew,增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。

使用GenericAPIView类一般需要实现queryset属性或者重写get_queryset方法

支持定义的属性:

  • 列表视图与详情视图通用:
    • queryset列表视图的查询集
    • serializer_class视图使用的序列化器
  • 列表视图使用:
    • pagination_class分页控制类
    • filter_backends过滤控制后端
  • 详情页视图使用:
    • lookup_field查询单一数据库对象时使用的条件字段,默认为’pk
    • lookup_url_kwarg查询单一数据时URL中的参数关键字名称,默认与look_field相同

提供的方法:

  • 列表视图与详情视图通用:

    • get_queryset(self)

      返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写,例如:

      def get_queryset(self):
          user = self.request.user
          return user.accounts.all()
      
    • get_serializer_class(self)

      返回序列化器类,默认返回serializer_class,可以重写,例如:

      def get_serializer_class(self):
          if self.request.user.is_staff:
              return FullAccountSerializer
          return BasicAccountSerializer
      
    • *get_serializer(self,_args, _kwargs)

      返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。

      注意,在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。

  • 详情视图使用:

    • **get_object(self)**返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。

      若详情访问的模型类对象不存在,会返回404。

      该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。

添加展示实现

class AdGeneric(GenericAPIView):
    queryset = Ad.objects.all()
    serializer_class = AdSer

    def get(self,request):
        ad = self.get_queryset()
        ser = self.get_serializer(ad,many=True)
        return Response(ser.data)
    def post(self,request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
        return Response({"code":200})

Mixin

ListModelMixin

列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。

该Mixin的list方法会对数据进行过滤和分页

from rest_framework.pagination import PageNumberPagination
from rest_framework.mixins import ListModelMixin

class PageClass(PageNumberPagination):
    page_size = 1 # 每页展示数据条数


# 对Test表中的数据进行分页展示
class TestMixin(GenericAPIView,ListModelMixin):
    queryset = Test.objects.all()
    serializer_class = Test_Serializer
    pagination_class = Pages

    def get(self,request):
        return self.list(request)
CreateModelMixin

创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。

如果序列化器对前端发送的数据验证失败,返回400错误。

from rest_framework.mixins import CreateModelMixin

class TestMixin(GenericAPIView,CreateModelMixin):
    queryset = Test.objects.all()
    serializer_class = Test_Serializer
   
    def post(self,request):
        return self.create(request)
UpdateModelMixin

更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。

同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。

成功返回200,序列化器校验数据失败时,返回400错误。

#re_path('admodify/(?P<pk>\d+)/$',AdMixin.as_view())

from rest_framework.mixins import UpdateModelMixin

class TestMixin(GenericAPIView,UpdateModelMixin):
    queryset = Test.objects.all()
    serializer_class = Test_Serializer
   
    def put(self,request,pk):
        return self.update(request)
DestroyModelMixin

删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。

成功返回204,不存在返回404。

from rest_framework.mixins import DestroyModelMixin,ListModelMixin

class TestMixin(GenericAPIView,DestroyModelMixin,ListModelMixin):
    queryset = Test.objects.all()
    serializer_class = Test_Serializer

    def get(self,request):
        return self.list(request)

    def delete(self,request,pk):
        return self.destroy(request)
RetrieveModelMixin

详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。

如果存在,返回200, 否则返回404。

from rest_framework.mixins import RetrieveModelMixin

class TestMixin(GenericAPIView,RetrieveModelMixin):
    queryset = Test.objects.all()
    serializer_class = Test_Serializer

    def get(self,request,pk):
        return self.retrieve(request)

子类视图

CreateAPIView

提供 post 方法

继承自: GenericAPIView、CreateModelMixin

class TestCreateView(CreateAPIView):    
		serializer_class = TestCreateSer
ListAPIView

提供 get 方法

继承自:GenericAPIView、ListModelMixin

class TeacherListView(ListAPIView):    
  	queryset = Test.objects.all()
	serializer_class = Test_Serializer
RetireveAPIView

提供 get 方法

继承自: GenericAPIView、RetrieveModelMixin

class GenericList(RetrieveAPIView):
    queryset = Test.objects.all()    
    serializer_class = Test_Serializer
    lookup_field='id' # 查询的字段
DestroyAPIView

提供 delete 方法

继承自:GenericAPIView、DestoryModelMixin

class GenericList(DestroyAPIView):
    queryset = Test.objects.all()    
    serializer_class = Test_Serializer
    lookup_field='id'
UpdateAPIView

提供 put 和 patch 方法

继承自:GenericAPIView、UpdateModelMixin

class TestUpdateView(UpdateAPIView):   
  	lookup_field = 'pk'
  	queryset = Test.objects.all()    
  	serializer_class = Test_Serializer
RetrieveUpdateAPIView

提供 get、put、patch方法

继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

class TestUpdateView(RetrieveUpdateAPIView):   
  	lookup_field = 'pk'
  	queryset = Test.objects.all()    
  	serializer_class = Test_Serializer
RetrieveUpdateDestoryAPIView

提供 get、put、patch、delete方法

继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

class TestUpdateView(RetrieveUpdateDestoryAPIView):   
  	lookup_field = 'pk'
  	queryset = Test.objects.all()    
  	serializer_class = Test_Serializer

视图集

视图集简单来说就是一群视图逻辑操作的功能合集,并可采用路由映射的方式进行功能选择,编写的内置逻辑方法不再是使用请求命名,而是使用功能来进行命名

视图集类不再实现 getpost 等方法,而是实现动作 actionlistcreate 等,视图集只在使用 as_view 方法的时候,才会将 action 动作与具体请求方式对应上

class CartRecordView(ViewSet):
    def list(self,request):
        record = CarRecord.objects.all()
        ser = CarRecordSer(record,many=True)
        return Response({'mes':ser.data})
    
    def retrieve(self,request,id):
        record = CarRecord.objects.filter(id=id).first()
        ser = CarRecordSer(record)
        return Response({'mes':ser.data})

    def create(self,request):
        record = CarRecordSer(data=request.data)
        if record.is_valid():
            record.save()
        return Response('ok')

那么他的路由映射不是之前的直接 as_view,还要对应采取对应请求进行映射

ViewSet

继承自 APIView,作用也与 APIView 基本类似,提供了身份认证权限校验流量管理

ViewSet 中,没有提供任何动作 action 方法,需要我们自己实现 action 方法

说白了,ViewSet 只是让我们可以在路由配置的地方可以进行请求映射,属于最基础的视图集基类

from rest_framework import viewsets
class UserViewSet(viewsets.ViewSet):
    def list(self,request):
        pass

    def retrieve(self,request,id):
        pass

    def create(self,request):
        pass 
     
    def update(self, request, id=None):
        print('update')

    def destroy(self, request, id=None):
        print('destroy')


path('viewset/', views.ModelViewSet.as_view({'get': 'list', 'post': 'create'})),
path('viewset/<int:pk>/',views.ModelViewSet.as_view({'get':'retrieve','put':'update','destroy': 'destroy'}))
GenericViewSet

继承自 GenericAPIView,作用也与 GenericAPIView 类似,提供了 get_objectget_queryset 等方法便于列表视图详情信息视图的开发

class CarViewSetM(GenericViewSet):
    queryset = CarRecord.objects.all()
    serializer_class = CarRecordSer
    lookup_field='id'

    def list(self,request):
        record = self.get_queryset()
        ser = self.get_serializer(record,many=True)
        return Response({'mes':ser.data})
    
    def retrieve(self,request,id):
        record = self.get_queryset()
        ser = CarRecordSer(record)
        return Response({'mes':ser.data})

    def create(self,request):
        record = CarRecordSer(data=request.data)
        if record.is_valid():
            record.save()
        return Response('ok')

    def update(self,request):
        instance = self.get_object()        
        serializer = self.get_serializer(instance=instance,data=request.data)
        serializer.is_valid(raise_exception=True)        
        instance = serializer.save()        
        return instance      

    def destory(self,request):
        record = self.get_queryset()
        record.delete()
        return Response('ok')
      
path('CarViewSetM/',views.CarViewSetM.as_view({'get':'list','post':'create'})),
    path('varViewSetDetail/<int:id>',views.CarViewSetM.as_view({'get':'retrieve','put':'update','delete':'destory'}))
ModelViewSet

ModelViewSet 从类继承 GenericAPIView,并包括用于各种动作实现方式中,通过在各种混入类的行为混合,包含了**.list**、.retrieve.create.update.partial_update、和**.destroy** 等方法,继承 ListModelMixinRetrieveModelMixinCreateModelMixinUpdateModelMixinDestroyModelMixin

需要至少提供 querysetserializer_class 属性

class CarViewSetM(ModelViewSet):
    queryset = CarRecord.objects.all()
    serializer_class = CarRecordSer
    lookup_field='id'
    
    
path('CarViewSetM/',views.CarViewSetM.as_view({'get':'list','post':'create'})),
    path('varViewSetDetail/<int:id>',views.CarViewSetM.as_view({'get':'retrieve','put':'update','delete':'destory'}))
ReadOnlyModelViewSet

ReadOnlyModelViewSet* 班也继承 GenericAPIView*,但只是提供了读取数据**的操作,含有的 action 有 *list* 和 *retrieve*

需要至少提供 *queryset* 和 *serializer_class* 属性

class CarViewSetM(ReadOnlyModelViewSet):
    queryset = CarRecord.objects.all()
    serializer_class = CarRecordSer
    lookup_field='id'

感谢关注!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楼下安同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值