9.26内容整理和概述
今日内容概要
内容目录
- APIView基本使用
- APIView源码分析
- Request类源码分析
- 序列化组件介绍
- 战略补充
APIView基本使用
本质:是一个第三方drf的app,只能在djagno上使用
注册:在settings.py的INSTALLED_APPS中添加'rest_framework' # 如果不注册当前app,浏览器访问会报错,postman不会;注册了zpp之后,浏览器访问会给出一个好看的界面
导包:from rest_framework.views import APIView # 在views.py文件中
APIView源码分析
继承APIView的类执行流程:
1.路由匹配成功,调用继承APIView的类的as_view方法
2.当前类中没有as_view方法,去调用父类APIView的as_view方法
3.APIView的as_view方法是一个闭包函数,它的主要功能:
3.1 取消csrf认证
3.2 调用APIView类的父类View类的as_view方法
4.View类的as_view方法主要功能:调用APIView类的dispatch方法
5.APIView类的dispatch方法步骤: # 核心
1.将传入的django原生的request变成drf提供的Request类的对象 # request = self.initialize_request(request, *args, **kwargs)
2.将新生成的drf提供的Request类的对象赋予传入APIView的request # self.request = request
3.对request执行认证,频率,权限 # self.initial(request, *args, **kwargs)
4.重现父类View类的dispatch方法:通过反射,根据请求方式调用当前类的方法
5.如果出现异常,捕获并且处理
Request类源码分析
1.__getattr__方法:
功能:
1.当Request类对象点出来的属性不在Request类中时,触发当前函数
2.调用djagno的request通过反射拿取数据并返回 # djagno的request:request._request / self._request
2.data方法:
功能:
1.被property装饰了,变成了数据属性调用
2.以后POST请求中body体中提交的数据,都从request.data取 # body可以含有三种数据类型:urlencoded,form-data,json
3.当请求数据类型为urlencoded,form-data时,request.data数据类型为QueryDict;当请求数据类型为json时,request.data数据类型为字典
3.query_params方法:get请求提交的参数从request.query_params取 # 等效代码:request._request.GET / request.GET
4.取文件:request.FILES # 和原生Django一样
序列化组件
使用背景:当我们需要向前端发送对象的json数据时,为了方便序列化,使用序列化组件
序列化步骤:
1.在app文件下创建serializer.py文件
2.在serializer.py文件中导包:from rest_framework import serializers
3.创建序列化类
例子:
class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField()
4.回到视图类调用BookSerializer类序列化对象:
1.当对象为一个时,直接实例化序列化类,并将对象赋予instance属性 # 例子:ser = BookSerializer(instance=book)
2.当对象为多个时,实例化序列化类,将对象赋予instance属性,并设置many属性为True # 例子:ser = BookSerializer(instance=book_list,many=True)
5.返回被序列化的对象的data属性值 # return Response(ser.data)
反序列化步骤:
'------------新增-------------'
1.当请求为post时,通过request.data获取数据
2.将获取的数据传入序列化类的data属性中,形成一个对象 # 例子:ser = BookSerializer(data=request.data)
3.校验前端传入的数据 # 例子:if ser.is_valid():
4.校验通过保存数据 # 例子:ser.save()
原理:调用save会触发BookSerializer的save方法,如果instance有值执行update,没有值执行create
4.1 当instance没有值时,我们需要在BookSerializer类中重写create方法
例子:
def create(self, validated_data):
res = Book.objects.create(**validated_data)
return res
5.再将保存成功的信息返回给前端
6.如果校验未通过,返回给前端错误信息
'------------修改-------------'
1.当请求为put时,通过request.data获取数据
2.根据条件查找出修改的对象
3.修改对象,将获取的数据传入序列化类的data属性中,并将修改对象赋予instance属性 # 例子:ser = BookSerializer(instance=book, data=request.data)
4.校验前端传入的数据 # 例子:if ser.is_valid():
4.校验通过保存数据 # 例子:ser.save()
原理:调用save会触发BookSerializer的save方法,如果instance有值执行update,没有值执行create
4.2 当instance有值时,我们需要在BookSerializer类中重写update方法
例子:
def update(self, instance, validated_data):
# instance要修改的对象
# validated_data 校验过后的数据
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish = validated_data.get('publish')
instance.save()
return instance
5.再将保存成功的信息返回给前端
6.如果校验为通过,返回给前端错误信息
战略补充(JsonResponse属性+request获取的数据类型+Response)
1.JsonResponse:
属性:
1.safe:
问题:当(括号内)返回数据类型不是字典是会报错 # 例子:return JsonResponse(res_list)
解决方法:添加safe属性,改为false # 例子:return JsonResponse(res_list,safe=False)
2.json_dumps_params:
问题:当(括号内)返回的数据乱码
解决方法:向当前属性设置ensure_ascii # 例子:return JsonResponse(res_list,safe=False,json_dumps_params{'ensure_ascii':False})
2.request在POST请求中body体获取的数据类型:
1.1 urlencoded:request.POST # 数据类型:querydict
1.1 urlencoded:request.body # 数据类型:二进制
2.1 form-data:request.POST # 数据类型:querydict
2.2 form-data:request.body # 数据类型:二进制;如果请求中带文件,调用request.body直接报错
3.json:request.body # 数据类型:二进制;request.POST无法取出json格式数据
3.drf的Response:可以返回任何类型的数据