drf之请求与响应、drf之视图组件

drf之请求与响应

Request

from rest_framework.request import Request

    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        # 二次封装request,将原生request作为drf request对象的 _request 属性
        self._request = request
    def __getattr__(self,item):
    	return getattr(self._request,item)
REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。

REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典[QueryDict]对象保存到Request对象中。

Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。

无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。

Request类:属性或方法

# 请求对象.data:前端以三种编码方式传入的数据,都可以取出来
# 请求对象.query_params 与Django标准的request.GET相同,只是更换了更正确的名称而已。

Response

from rest_framework.response import Response

REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。

REST framework提供了Renderer 渲染器,用来根据请求头中的Accept(接收数据类型声明)来自动转换响应数据到对应格式。如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式。

Response类:属性或方法

 def __init__(self, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):
        
#data:你要返回的数据,字典
#status:返回的状态码,默认是200,
	-from rest_framework import status在这个路径下,它把所有使用到的状态码都定义成了常量
#template_name 渲染的模板名字(自定制模板),不需要了解
#headers:响应头,可以往响应头放东西,就是一个字典
#content_type:响应的编码格式,application/json和text/html;

drf能够解析的请求编码,响应编码

响应状态码

# 正常返回信息1xx 
HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
# 返回成功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
# 重定向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
# 客户端错误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
# 客户端错误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

请求编码

能够解析的请求编码

默认能够解析:urlencoded、form-data、json

其实通过配置完成:项目没有配置,是在drf内置的配置文件中提前好了

drf也是有俩套的:
    一套是项目中得配置(settings.py),一套是默认的配置
    drf的配置文件settings.py中有DEFAULT_PARSER_CLASSES(默认的解析类)
        -'rest_framework.parsers.JSONParser', 可以解析json格式
        -'rest_framework.parsers.FormParser', 可以解析urlencoded格式
        -'rest_framework.parsers.MultiPartParser' 可以解析form-data格式

想让我们的接口只能接受json格式

方式一:全局配置---》项目配置文件---》以后所有的接口都遵循这个配置
REST_FRAMEWORK = {
        'DEFAULT_PARSER_CLASSES': [
            'rest_framework.parsers.JSONParser',
            # 'rest_framework.parsers.FormParser',
            # 'rest_framework.parsers.MultiPartParser',
        ],
    }
方式二:局部配置
class TestView(APIView):
    parser_classes = [JSONParser,FormParser,MultiPartParser]# 注意列表里的类需要先导入, parser_classes这个可以在apiview里看到默认的

image

总结

解析类的使用顺序:优先用视图类自己的,然后用项目配置文件,最后用内置的
实际项目如何配置:
    -基本上都运行JSONParser,FormParser
    -如果上传文件只允许MultiPartParser

drf之视图组件

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

APIView与View的不同之处

传入到视图方法中的是REST framework的对象,而不是Django的HttpResponse对象;

视图方法可以返回REST framework的Response对象,视图会为响应数据设置符合前端要求的格式;

任何APIView异常都会被捕获到,并且处理成适合的响应信息;

在进行dispatch分发前,会对请求进行身份认证、权限检查、流量控制。(就是之前我对于apiview源码分析出来之后的结果)

2个视图基类和其他扩展视图类

由于drf提供了一个顶层的视图类APIView,我们可以通过继承APIView写视图类

但是后期我们可能需要序列化的表比较多,这可能就需要我们重复的书写视图函数的五个接口,这时候我们就可以使用面向对象的继承,封装,使用GenericAPIView进行书写视图函数的5个接口

# APIView

# GenericAPIView-->继承了APIView
	-类属性:
    	queryset = User.objects.all()  #queryset传一个queryset对象
    	serializer_class = UserSerializer # serializer_class传我们需要用自己定义的那个序列化类来序列化数据
    -方法:
    	 self.get_object() # 根据pk获取单个数据
         self.get_serializer # 获取要使用的序列化类
         self.get_queryset() # 获取所有要序列化数据

原来我们基于apiview写的5个接口是这样的:

class UserView(APIView):
    def get(self, request):
        book_list = User.objects.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 UserDetailView(APIView):
    def get(self, request, pk):
        book = User.objects.filter(pk=pk).first()
        ser = UserSerializer(instance=book)
        return Response(ser.data)

    def put(self, request, pk):
        book = User.objects.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.objects.filter(pk=pk).delete()
        return Response('{'code': 100, 'msg': '删除成功'}')

现在我们基于GenericAPIView写5个接口:

queryset = User.objects.all()
serializer_class = UserSerializer
对于不同的模型表,开设的接口我们只需要该上面两行代码就行

from rest_framework.generics import GenericAPIView
class UserView(GenericAPIView):
    queryset = User.objects.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.objects.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('{'code': 100, 'msg': '删除成功'}')

进一步优化:基于GenericAPIView和5个视图扩展类写的接口

from rest_framework.mixins import  ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
# views.py
class Book3View(GenericAPIView,ListModelMixin,CreateModelMixin):

    queryset=Book.objects
    serializer_class = BookSerializer
    def get(self,request):
        return self.list(request)

    def post(self,request):
        return self.create(request)

class Book3DetailView(GenericAPIView,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin):
    queryset = Book.objects
    serializer_class = BookSerializer
    def get(self, request,pk):
        return self.retrieve(request,pk)

    def put(self, request,pk):
        return self.update(request,pk)

    def delete(self,request,pk):
        return self.destroy(request,pk)
# urls.py
    # 使用GenericAPIView+5 个视图扩展类  重写的
    path('books3/', views.Book3View.as_view()),
    re_path('books3/(?P<pk>d+)', views.Book3DetailView.as_view()),

再优化:基于GenericAPIView的9个视图子类编写的接口

from rest_framework.generics import ListAPIView,CreateAPIView,   RetrieveAPIView,DestroyAPIView,UpdateAPIView
from rest_framework.generics import ListCreateAPIView,     RetrieveUpdateDestroyAPIView,RetrieveUpdateAPIView,RetrieveDestroyAPIView
# 正常来讲  Destroy+Update 应该有一个  ,作者没加
class UserView(ListCreateAPIView):
    # 配置两个 类属性
    queryset = User.objects.all()
    serializer_class = UserSerializer
class UserDetailView(RetrieveUpdateDestroyAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
*1) CreateAPIView*
提供 post 方法
继承自: GenericAPIView、CreateModelMixin

*2)ListAPIView*
提供 get 方法
继承自:GenericAPIView、ListModelMixin

*3)RetireveAPIView*
提供 get 方法
继承自: GenericAPIView、RetrieveModelMixin

*4)DestroyAPIView*
提供 delete 方法
继承自:GenericAPIView、DestoryModelMixin

*5)UpdateAPIView*
提供 put 和 patch 方法
继承自:GenericAPIView、UpdateModelMixin

*6)RetrieveUpdateAPIView*
提供 get、put、patch方法
继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

*7)RetrieveUpdateDestoryAPIView*
提供 get、put、patch、delete方法
继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

*8) ListCreateAPIView*
提供 get、post方法
继承自:GenericAPIView、CreateAPIView、ListAPIView

*9) RetrieveDestroyAPIView*
提供 get、delete方法
继承自:GenericAPIView、RetireveAPIView、DestroyAPIView

再进一步优化:使用ModelViewSet编写5个接口

# views.py 
from rest_framework.viewsets import ModelViewSet
class Book5View(ModelViewSet):  #5个接口都有,但是路由有点问题
    queryset = Book.objects
    serializer_class = BookSerializer
    
# urls.py
# 使用ModelViewSet编写5个接口
    path('books5/', views.Book5View.as_view(actions={'get':'list','post':'create'})), #当路径匹配,又是get请求,会执行Book5View的list方法
    re_path('books5/(?P<pk>d+)', views.Book5View.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),

继承ViewSetMixin视图类的视图类,类中的方法可以不必一定写成get、post

# views.py
from rest_framework.viewsets import ViewSetMixin
class Book6View(ViewSetMixin,APIView): #一定要放在APIVIew前
    def get_all_book(self,request):
        print("xxxx")
        book_list = Book.objects.all()
        book_ser = BookSerializer(book_list, many=True)
        return Response(book_ser.data)
    
# urls.py
    #继承ViewSetMixin的视图类,路由可以改写成这样
    path('books6/', views.Book6View.as_view(actions={'get': 'get_all_book'})),

image

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:drf之请求与响应、drf之视图组件 - Python技术站

(0)
上一篇 2023年4月2日
下一篇 2023年4月2日

相关文章

  • 操作系统的介绍

    操作系统的介绍 1.什么是操作系统 操作系统其实就是一个协调、管理、控制计算机硬件资源和软件资源的一个控制程序 2.为什么要有操作系统 (1)可以控制计算机硬件的基本运行(2)把操作硬件的复杂操作封装成一个简单的功能,交给上层的应用程序使用。例如文件就是操作系统提供给应用程序的一种功能! 3.程序的区分 计算机硬件是死的,计算机硬件的运行是受软件控制的、所以…

    2023年4月2日
    00
  • form表单内容序列化的两种方法

    form表单内容序列化 form表单自带两种方法serialize()方法和serializeArray()方法 1.serialize()方法 描述:序列化表单内容为字符串(不包括文件),用于Ajax请求。 格式:var data = $(‘#form’).serialize(); 2.serializeArray()方法 描述:序列化表单元素(类似’.s…

    2023年4月2日
    00
  • 认证

    认证的实现 使用步骤: # 通过认证类完成,使用步骤 1 写一个认证类,继承BaseAuthentication 2 重写authenticate方法,在内部做认证 3 如果认证通过,返回2个值 4 认证不通过抛AuthenticationFailed异常 5 只要返回了两个值,在后续的request.user 就是当前登录用户 认证源码分析: https:…

    Python开发 2023年4月2日
    00
  • 基础数据类型之数字和字符串

    1.数字类型 数字类型的数据可以相互的进行+-/*、也可以进行相互的比较(<>=) 1.1整型int age = 18 记录年龄等整数 print(type(age))# int类型 int()方法可以将其他类型的数据转换成int类型 1.1.2二、八、十六进制的相互转换 1.十进制《—》二进制 # bin()方法 print(bin(11)…

    Python开发 2023年4月2日
    00
  • flask操作数据库

    flask操作数据库 准备工作 安装flask-script(版本过高可能会报错) pip install flask-script==2.0.3 使用flask-script里的Manager类实例化来管理项目的启动等 from apps import create_app from flask_script import Manager app = cr…

    2023年4月2日
    00
  • django中CBV视图模式的View源码分析

    位置: 1.找到自己项目用的解释器存储位置H:\pythonProject\Lib\site-packages\django\views\generic\base.py在base.py里有一个View类 2.也可以通过from django.views import View 按住ctrl点击View会直接跳到该类的位置 CBV形式的路由 path(r’^l…

    Python开发 2023年4月2日
    00
  • 面向对象高级–反射、内置方法和元类

    1.反射 1.1什么是反射 python是一门动态语言,而反射机制被视为动态语言的关键! 反射机制指的是:在程序的运行过程中,动态的获取程序的信息和对象的功能! ‘动态’:指一开始不知道程序的信息和对象的功能,只有等到运行到那的时候才会动态获取!!! 比如:x=18 在程序运行的时候,python才会通过反射机制动态的获取到这个值是整型,并不需要一开始定义的…

    Python开发 2023年4月2日
    00
  • django中的auth模块与admin后台管理

    1. auth模块 在创建完django项目之后,执行数据库迁移之后,数据库里会增加很多新表,其中有一张名为auth_user的表,当访问django自带的路由admin的时候,需要输入用户名和密码,其参照的就是auth_user表 使用python3 manage.py crataesupperuser 可以创建超级管理员用户,同时在auth_user表里…

    2023年4月2日
    00
合作推广
合作推广
分享本页
返回顶部