• Django-rest-framework框架之drf请求与响应及2个视图基类


    今日内容概述

    • drf请求与响应
    • drf之视图组件
    • drf视图组件之2个视图基类
    • drf视图组件之5个视图扩展类
    • drf视图组件之9个视图子类
    • drf视图组件之视图集

    drf请求与响应

    1.Request和Response类

    • Request:framework传入视图的request对象不再是Django默认的HttpRequest对象,卫视farmework提供的扩展了HttpRequest类的对象。
      Request独享的数据是自动根据前端发送数据的格式进行解析之后的结果.

    常用属性:

    1.data:
    
    request.data返回解析之后的请求体数据。
    类似于Django中标准的request.POST和request.FILES属性,但提供如下特性:
    
    (1)包含了解析之后的文件盒非文件数据;
    (2)包含了对POST,PUT,PATCH(修改的请求方式)请求方式解析后的数据;
    (3)利用了REST farmework的parsers解析器,不仅支持表单类型数据,也支持JSON数据。
    
    2)query_params:
    
    request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。
    底层原理__getattr__
    
    • Response:farmework提供了一个响应类Response,使用该类构造响应对象时,相应的具体数据内容会被转换成符合前端需求的类型。

    构造方法:

    Response(data, status=None, template_name=None, headers=None, content_type=None)1)data=None:字典,列表序列化成json格式字符串,返回给前端(这时数据放在http响应的body中)
    
    (2)status=None:http相应的状态码,默认是200,201;drf默认帮所有的http响应状态码都做成了常量,可以直接导进去使用。
    
    (3)headers=None:http的响应头,字典{name:lqz}
    -原生django要在响应头中加数据:
    res=JsonResponse(d)
    res['rrr']='yyy'
    return res
    
    (4)template_name=None:在浏览器中看到好看的页面,指定的模板;
    
    (5)content_type=None:响应的编码格式(json)
    
    • 为了方便设置状态码,REST framewrok在rest_framework.status模块中提供了常用状态码常量。
    1)信息告知 - 1xx
    HTTP_100_CONTINUE
    HTTP_101_SWITCHING_PROTOCOLS
    
    (2)成功 - 2xx
    HTTP_200_OK
    HTTP_201_CREATED
    HTTP_202_ACCEPTED
    HTTP_203_NON_AUTHORITATIVE_INFORMATION
    HTTP_204_NO_CONTENT
    HTTP_205_RESET_CONTENT
    HTTP_206_PARTIAL_CONTENT
    HTTP_207_MULTI_STATUS
    
    (3)重定向 - 3xx
    HTTP_300_MULTIPLE_CHOICES
    HTTP_301_MOVED_PERMANENTLY
    HTTP_302_FOUND
    HTTP_303_SEE_OTHER
    HTTP_304_NOT_MODIFIED
    HTTP_305_USE_PROXY
    HTTP_306_RESERVED
    HTTP_307_TEMPORARY_REDIRECT
    
    (4)客户端错误 - 4xx
    HTTP_400_BAD_REQUEST
    HTTP_401_UNAUTHORIZED
    HTTP_402_PAYMENT_REQUIRED
    HTTP_403_FORBIDDEN
    HTTP_404_NOT_FOUND
    HTTP_405_METHOD_NOT_ALLOWED
    HTTP_406_NOT_ACCEPTABLE
    HTTP_407_PROXY_AUTHENTICATION_REQUIRED
    HTTP_408_REQUEST_TIMEOUT
    HTTP_409_CONFLICT
    HTTP_410_GONE
    HTTP_411_LENGTH_REQUIRED
    HTTP_412_PRECONDITION_FAILED
    HTTP_413_REQUEST_ENTITY_TOO_LARGE
    HTTP_414_REQUEST_URI_TOO_LONG
    HTTP_415_UNSUPPORTED_MEDIA_TYPE
    HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
    HTTP_417_EXPECTATION_FAILED
    HTTP_422_UNPROCESSABLE_ENTITY
    HTTP_423_LOCKED
    HTTP_424_FAILED_DEPENDENCY
    HTTP_428_PRECONDITION_REQUIRED
    HTTP_429_TOO_MANY_REQUESTS
    HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
    HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
    
    (5)服务器错误 - 5xx
    HTTP_500_INTERNAL_SERVER_ERROR
    HTTP_501_NOT_IMPLEMENTED
    HTTP_502_BAD_GATEWAY
    HTTP_503_SERVICE_UNAVAILABLE
    HTTP_504_GATEWAY_TIMEOUT
    HTTP_505_HTTP_VERSION_NOT_SUPPORTED
    HTTP_507_INSUFFICIENT_STORAGE
    HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
    

    2.drf能够解析的请求编码

    • 默认能解析的请求编码:
      urllencoded
      form-data
      json
    • 请求编码主要通过配置来完成:
      (1)drf中有两套配置,一套是项目中的配置(settings.py),一套是默认配置;
      (2)drf的配置文件settings.py中有DEFAULT_PARSER_CLASSES(默认的解析类)
    'rest_framework.parsers.JSONParser', 可以解析json格式
    'rest_framework.parsers.FormParser', 可以解析urlencoded格式
    'rest_framework.parsers.MultiPartParser' 可以解析form-data格式
    
    • 这边来个需求实际展示一下配置
    需求:想让我们的接口只能接收json格式:
    
    方式一:全局配置,则在drf的项目配置文件中修改(对于不需要的格式注释掉即可)
    
    REST_FRAMEWORK = {
          'DEFAULT_PARSER_CLASSES': [
          'rest_framework.parsers.JSONParser',
          # 'rest_framework.parsers.FormParser',
          # 'rest_framework.parsers.MultiPartParser',
          ],
    }
    
    方式二:局部配置(在类中直接进行配置)
    
    class TestView(APIVew):
    	parser_classes =[JSONParser]
    
    • 解析类的使用顺序:
      优先使用类本身的解析,然后使用项目配置文件里的,最后用内置的
    • 实际项目请求解析配置:
      基本上都运行JSONParser,FormParser
      如果上传文件只允许MultiPartParser

    3.drf能够解析的响应编码

    • 如果用浏览器的话会自行出现很好看的页面效果,如果用postman看到的是json格式;
      默认情况下,相应的编码都是根据客户端类型决定的。
    • 两种配置方发:
    方式一:全局配置,在项目的配置文件:
    
       REST_FRAMEWORK = {
           'DEFAULT_RENDERER_CLASSES': [
               'rest_framework.renderers.JSONRenderer', # json格式
               'rest_framework.renderers.BrowsableAPIRenderer', #浏览器的格式
           ]
       }
       
    方式二:局部配置(同样可以选择配置)
    
    class TestView(APIView):
       renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
    

    drf之视图组件

    1.Django REST framwork 提供的视图的主要作用:

    • 控制序列化器的执行(检验、保存、转换数据)
    • 控制数据库查询的执行

    2.视图继承关系
    在这里插入图片描述
    REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写。

    drf视图组件之2个视图基类

    1.2个视图基类

    • APIView
    rest_framework.views.APIView
    

    (1)APIView是REST framework提供的所有视图的基类,继承自Django的View父类。
    (2)APIView与View的不同:
    传入到视图的方法中的是REST framwork的Request对象,而不是Django中的HttpRequest对象;
    视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
    任何APIException异常都会被捕获到,并且处理成合适的响应信息;
    在进行dispatch()分发前,会对请求进行身份认证、权限检查、频率控制。

    • GenericAPIView–>继承了APIView
    rest_framework.generics.GenericAPIView
    

    (1)继承自APIVIew,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类。
    (2)提供的关于序列化器使用的属性与方法

    属性:serializer_class 指明视图使用的序列化器
    例如:serializer_class = UserSerializer
    
    方法:get_serializer(self, args, *kwargs) 获取要使用的序列化类
    

    (3)提供的关于数据库查询的属性与方法

    属性:queryset 指明使用的数据查询集
    例如:queryset = User.objects.all()
    
    方法:get_queryset(self)  获取所有要序列化数据
    返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset属性,
    例如:
    def get_queryset(self):
    	user = self.request.user
    	return user.accounts.all()
    get_object(self)  根据pk获取单个数据
    返回详情视图所需的模型类数据对象,返回详情视图所需的模型类数据对象。
    

    2.基于APIView写5个接口

    class UserView(APIView):
       def get(self,request):
           book_list = User.object.all()
           ser = UserSerializer(instance=book_list,many=True)
           return Response(ser.data)
    
       def post(self,request):
           ser = UserSerializer(data=request.data)
           if ser.is_valid():
             ser.save()
               return Response({'code':100,'msg':"新增成功"},status=201)
           else:
               return Response({'code':101,'msg':ser.errors})
    
    
    class UserDatailView(APIView):
       def get(self,request,pk):
           book = User.object.filter(pk=pk).first()
           ser = UserSerializer(instance=book)
           return Response(ser.data)
    
       def put(self,request,pk):
           book = User.object.filter(pk=pk).first()
           ser = UserSerializer(instance=book,data=request.data)
           if ser.is_valid():
               ser.save()
               return Response({'code':100,'msg':"新增成功"},status=201)
           else:
               return Response({'code': 101, 'msg': ser.errors})
    
    
       def delete(self,request,pk):
           User.object.filter(pk=pk).delete()
           return Response('')
    

    3.基于GenericAPIView写5个接口

    from rest_framework.generics import GenericAPIView
    class UserView(GenericAPIView):
       queryset = User.object.all()
       serializer_class = UserSerializer
    
       def get(self,request):
           book_list = self.get_queryset()
           ser = self.get_serializer(instance=book_list,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':100,'msg':"新增成功"},status=201)
           else:
               return Response({'code':101,'msg':ser.errors})
           
    class UserDetailView(GenericAPIView):
       queryset = User.object.all()
       serializer_class = UserSerializer
       def get(self,request,pk):
           book = self.get_object()
           ser = self.get_serializer(instance=book)
           return Response(ser.data)
       
       def put(self,request,pk):
           book = self.get_object()
           ser = self.get_serializer(instance=book,data=request.data)
           if ser.is_valid():
               ser.save()
               return Response({'code':100,'msg':"修改成功"},status=201)
           else:
               return Response({'code':101,'msg':ser.errors})
           
       def delete(self,request,pk):
           self.get_queryset().filter(pk=pk).delete()
           return Response('')
    

    drf视图组件之5个视图扩展类

    必须配合GenericAPIView使用,不能配合APIVew使用。

    from rest_framework.mixins import RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, ListModelMixin
    

    1.基于GenericAPIView+5个视图扩展类写接口
    作用:
    提供了几种后端视图(对数据资源进行增删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。
    这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。
    列举:

    • (1)ListModelMixin(list方法,就是原来咱们的get):
      列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。
      该Mixin的list方法会对数据进行过滤盒分页。

    • (2)CreateModelMixin(写了一个Create方法,就是原来咱们post中的代码):
      创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。
      如果序列化器对前端发送的数据验证失败,返回400错误。

    • (3)RetrieveModelMixin(retrieve,就是咱们原来的get):
      详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。
      如果存在,返回200,否则返回404.

    • (4)UpdateModelMixin(update方法,就是咱们原来的put):
      更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。
      同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。
      成功返回200,序列化器校验数据失败时,返回400错误。

    • (5)DestoryModelMixin(destroy方法,就是原来咱们的delete):
      删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。
      成功返回204,不存在返回404.
      代码列举:

    class UserView(GenericAPIView,ListModeLMixin,CreateModelMixin):
    # 配置两个类属性
    	queryset = User.object.all()
    	serializer_class = UserSerializer
    	def get(self,request,*args,**kwargs):
    		return self.list(request,*args,**kwargs)
    
    	def post(self,request,*args,**kwargs):
    		return self.create(request,*args,**kwargs)
    
    class UserDetailView(GenericAPIView,RetrieveModelMiXin,UpdataModelMixin,DestoryModelMixin):
    	queryset = User.objects.all()
    	serializer_class = UserSerializer
    
    	def get(self,request,*args,**kwargs):
    		return self.update(request,*args,**kwargs)
    	def put(self,request,*args,**kwargs):
    		return srlf.update(request,*args,**kwargs)
    	def delete(self,request,*args,**kwargs):
    		return self.destory(request,*args,**kwargs)
    

    drf视图组件之9个视图子类

    视图类:继承GenericAPIView+某个或某几个视图扩展类

    from rest_framework.generics import ListAPIView,CreateAPIView,   RetrieveAPIView,DestroyAPIView,UpdateAPIView
    from rest_framework.generics import ListCreateAPIView,     RetrieveUpdateDestroyAPIView,RetrieveUpdateAPIView,RetrieveDestroyAPIView
    

    列举一些:
    (1)CreateAPIView
    提供post方法
    继承自GenericAPIView,CreateModelMinxin
    (2)ListAPIView
    提供get方法
    继承自GenericAPIView,ListModelMixin
    (3)RetrieveAPIView
    提供get方法
    继承自GenericAPIView,RetrieveModelMixin
    (4)DestoryAPIView
    提供delete方法
    继承自GenericAPIView、DestoryModelMixin
    (5)UpdateAPIView
    提供get和patch方法
    继承自:GenericAPIView、UpdateModelMixin
    (6)RetrieveUpdateAPIView
    提供 get、put、patch方法
    继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
    (7)RetrieveUpdateDestoryAPIView
    提供 get、put、patch、delete方法
    继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

    举几个栗子:

    class UserView(ListCreateAPIView):
       # 配置两个 类属性
       queryset = User.objects.all()
       serializer_class = UserSerializer
    class UserDetailView(RetrieveUpdateDestroyAPIView):
       queryset = User.objects.all()
       serializer_class = UserSerializer
    

    drf视图组件之视图集

    1.使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
    list() 提供一组数据
    retrieve() 提供单个数据
    create() 创建数据
    update() 保存数据
    destory() 删除数据
    ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。

    视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。

    2.常用视图集父类
    1) ViewSet
    继承自APIView与ViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

    ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{‘get’:’list’})的映射处理工作。

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

    2)GenericViewSet
    使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView。

    GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIView与ViewSetMixin,在实现了调用as_view()时传入字典(如{‘get’:‘list’})的映射处理工作的同时,还提供了GenericAPIView提供的基础方法,可以直接搭配Mixin扩展类使用。

    3)ModelViewSet
    继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

    4)ReadOnlyModelViewSet
    继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin。

    总结

    #两个基类
    APIView
    GenericAPIView:有关数据库操作,queryset 和serializer_class
    
    
    #5个视图扩展类(rest_framework.mixins)
    CreateModelMixin:create方法创建一条
    DestroyModelMixin:destory方法删除一条
    ListModelMixin:list方法获取所有
    RetrieveModelMixin:retrieve获取一条
    UpdateModelMixin:update修改一条
    
    #9个子类视图(rest_framework.generics)
    CreateAPIView:继承CreateModelMixin,GenericAPIView,有post方法,新增数据
    DestroyAPIView:继承DestroyModelMixin,GenericAPIView,有delete方法,删除数据
    ListAPIView:继承ListModelMixin,GenericAPIView,有get方法获取所有
    UpdateAPIView:继承UpdateModelMixin,GenericAPIView,有put和patch方法,修改数据
    RetrieveAPIView:继承RetrieveModelMixin,GenericAPIView,有get方法,获取一条
    
    
    ListCreateAPIView:继承>ListModelMixin,CreateModelMixin,GenericAPIView,有get获取所有,post方法新增
    RetrieveDestroyAPIView:继承RetrieveModelMixin,DestroyModelMixin,GenericAPIView,有get方法获取一条,delete方法删除
    RetrieveUpdateAPIView:继承RetrieveModelMixin,UpdateModelMixin,GenericAPIView,有get获取一条,put,patch修改
    RetrieveUpdateDestroyAPIView:继承RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView,有get获取一条,put,patch修改,delete删除
    
    #视图集
    ViewSetMixin:重写了as_view 
    ViewSet:     继承ViewSetMixin和APIView
    
    GenericViewSet:继承ViewSetMixin, generics.GenericAPIView
    ModelViewSet:继承>mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet
    ReadOnlyModelViewSet:继承>mixins.RetrieveModelMixin,mixins.ListModelMixin,GenericViewSet
    
  • 相关阅读:
    这就叫“面试造火箭,工作拧螺丝!”
    C++ | Leetcode C++题解之第123题买卖股票的最佳时机III
    网络安全之反序列化漏洞复现
    react native使用3-基础环境搭建1
    Android Surface 是如何跨进程传递的?
    使用node实现websocket
    Serverless如何赋能餐饮行业数字化?乐凯撒思变之道
    [算法笔记]最长递增子序列和编辑距离
    ROS知识点——消息过滤器 ( message_filters)
    java ssm大学教室管理系统springboot
  • 原文地址:https://blog.csdn.net/DiligentGG/article/details/127107433