drf知识点总结、请求与响应、视图组件

drf的整体知识点

前后端开发模式

API接口、postman使用、序列化和反序列化、restful规范

drf就是django的第三方app,能够快速实现符合restful规范的接口

cbv的执行流程:

路由匹配成功后,执行对应的视图类(视图类.as_view()),也就是执行View的as_view方法里面的闭包函数view,返回了self.dispatch(request,*args,**kwargs)方法

View中dispatch方法:根据请求的方式,执行视图函数中以请求方式命名的方法

反射

通过字符串动态的获取,设置,判断,对象中的属性或方法

getattr:	res=getattr(self,'run',None)
setattr:	setattr(self,'speak',内存地址)  self.speak()
hasattr:	hasattr(self,'run')

APIView

继承了View,执行流程

1. APIView的as_view调用了父类的as_view,返回了不需要csrf认证的view
2. 请求来了,执行View的as_view的闭包view,执行了APIView中的dispatch方法
3. APIView中的dispatch
   * 1. 包装了新的request
   * 2. 在执行视图函数之前:执行了三大认证
   * 3. 执行了视图函数:请求方式是什么,就执行视图函数中的什么方法
   * 4. 全局异常捕获:全局异常,统一返回格式

序列化类

Serializer、ModelSerializer、序列化、反序列化、校验

请求与响应

Request类:属性和方法、Response类

视图层

2基类、5个扩展类、9个子类、视图集

路由的使用

认证,频率,权限

过滤、排序、分页

全局异常处理

接口文档:自定生成,自己写

前后端分离:jwt认证方式,登录
公式内部:RBAC

django:admin 美化

drf之请求与响应

Request和Response类

继承APIView后,请求对象request中,每一次请求都是一个新的request

Request类

REST framework传入视图的request对象不再是django默认的HttpResquest对象,而是REST framework提供的扩展了HttpResquest类的Request类的对象。

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

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

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

data

request.data返回解析之后的请求体数据。类似于django中标准的request.POST和request.FILES属性,但提供如下特性:

  • 包含了解析之后的文件和非文件数据
  • 包含了对POST、PUT、PATCH请求方式解析的数据
  • 利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据

注意:put提交的数据在request.POST中取不到的

query_params

与django标准的request.GET相同,只是更换了更正确的名称而已。

其他的用起来跟之前一样用(FILES,method,path...), 底层实现原理就是:__getattr__

Response类

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

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

配置

可以在rest_framework.settings查找所有的drf默认配置项

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
        'rest_framework.renderers.JSONRenderer',  # json渲染器
        'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器
    )
}

构造方式

Response(data,status=None,template_name=None,headers=None,content_type=None)

data数据不要时render处理之后的数据,只需要传递python的内建数据类型即可,restframework会使用renderer渲染器处理data

data不能是复杂结构的数据,如django的模型类对象,对于这样的数据我们可以使用Serializer序列化器序列化处理后(转为了python字典类型)在传递给data参数。

参数说明

  • data:为响应准备的序列化处理后的数据,也就是序列化成的json格式字符串。放在响应的body中了。
  • status:状态码,默认为200,drf把所有的http响应状态码都做成了常量,可以直接导进来用
  • template_name:模版名称,如果使用HTMLRenderer时需指名
  • headers:用于存放响应头信息的字典:headers={'name':'Jason'}
  • content_type:响应数据的Content_Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。

原生django中在响应头中加数据:4个响应都可以这样写

res=JsonResponse(d)
res['rrr']='yyy'
return res
image-20220929164000625

常用属性

  • data:传给response对象的序列化后,但尚未render处理的数据。
  • status_code:状态码的数字
  • content:经过render处理后的响应数据

状态码

为了方便设置状态码,REST framework在rest_framework.status模块中提供了常用状态码常量

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

能够解析的请求编码

  • 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格式

指定接口的能够解析的请求编码格式

方式1:全局配置,到项目配置文件。以后所有的接口都遵循这个配置

REST_FRAMEWORK = {
            'DEFAULT_PARSER_CLASSES': [
                'rest_framework.parsers.JSONParser',
                'rest_framework.parsers.FormParser',
                # 'rest_framework.parsers.MultiPartParser',  # 不支持form-data格式
            ],
        }

配置了指定的请求编码,那么在配置文件中的请求编码就无法通过解析了。

image-20220929165937454

方式2:局部配置

class Books(GenericAPIView):
    parser_classes = [JSONParser]  # 在视图类中指定json格式编码格式,后续配置文件,drf配置文件的设置都失效

总结

解析类的使用顺序:优先用视图类自己的,然后用项目配置文件,最后用内置的

实际项目中如何配置

基本上都运行JSONParser,FormParser

如果上传文件只允许MultiPartParser

能够解析的响应编码

浏览器的好看的样式,postman看到json格式

默认情况下,响应的编码是根据客户端类型决定的

全局配置:在项目的配置文件

REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': [
            # 'rest_framework.renderers.JSONRenderer', # json格式
            'rest_framework.renderers.BrowsableAPIRenderer', #浏览器的格式
        ]
    }

局部配置

class TestView(APIView):
    renderer_classes = [JSONRenderer,]

在实际编码中,响应一般不配,就应默认

drf之视图组件

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

后期我们要写的代码可能重复代码比较多,就可以使用面向对象的继承,封装

2个视图基类

  • APIView
  • GenericAPIView(继承了APIView)

类属性

queryset=User.objects

# 如果是queryset对象也可以写User.objects.all(),源码
if isinstance(queryset, QuerySet):
  queryset = queryset.all()

serializer_class=UserSerializer:指定要序列化类

方法

self.get_object()  # 根据pk获取单个数据,还是要在请求方法里面带指定的参数,GenericAPIView视图类会通过此参数过滤出数据
self.get_serializer  # 获取要使用的序列化类
self.get_serializer(instance=Book,data=request.data)  # 获取所有要序列化数据,也可以用另一种写法

self.get_serializer_class()(instance=Book,data=request.data)

基于APIView写5个接口

class Books(APIView):
    def get(self,request):
        res=Book.objects.all()
        ser=BookSerializer(instance=res,many=True)
        return Response(ser.data)
    def post(self,request):
        ser=BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code':100,'msg':'新增成功'},status=201)
        else:
            return Response(ser.errors)
class BookDetail(APIView):
    def get(self,request,pk):
        res=Book.objects.filter(pk=pk).first()
        ser=BookSerializer(instance=res)
        return Response(ser.data)
    def put(self, request, pk):
        res = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=res, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '修改成功'}, status=201)
        else:
            return Response(ser.errors)
    def delete(self,request,pk):
        Book.objects.filter(pk=pk).delete()
        return Response('')

基于GenericAPIView写5个接口

class Books(GenericAPIView):
    queryset = Book.objects
    serializer_class = BookSerializer
    def get(self,request):
        # 获取当前数据对象
        res=self.get_queryset()
        ser=self.get_serializer(instance=res,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(ser.errors)
class BookDetail(GenericAPIView):
    queryset = Book.objects
    serializer_class = BookSerializer

    def get(self,request,pk):
        res=self.get_object()
        ser=self.get_serializer(instance=res)
        return Response(ser.data)
    def put(self,request,pk):
        res = self.get_object()
        ser = self.get_serializer(instance=res, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '修改成功'}, status=201)
    def delete(self,request,pk):
        self.get_object().delete()
        return Response('')

posted @ 2022-09-29 22:54  荀飞  阅读(178)  评论(0编辑  收藏  举报