APIView基本使用
1.什么是APIView
? ? ? ? Django中视图views.py有两种一种是基于类的实现另一种是函数的实现,而APIView就是REST framework提供的所有视图的基类,继承了Django的View
2.APIView与View的区别
? ? ? ? View是Django默认的视图基类,APIView是REST framework提供的所有视图基类并继承了Django的view
? APIView传入到视图方法中的是REST framework的Request对象而不是Django的HttpRequest对象
? 视图方法可以返回REST framework的Response对象,视图会设置响应数据render符合前端要求的格式
? 任何APIException异常都会被捕获到并处理成合适的响应信息
3.APIView+drf的Response
? ? ? ? 在用APIView视图类写的时候因为导入的drf是一个第三方app且只能在Django上使用所以不要忘了在settings.py文件中注册rest_framework这个app
from rest_framework.views import APIView
from rest_framework.response import Response
from res_framework.request import Request
class BookView(APIView): # APIview继承Django的View
def get(self,request):
# 获取所有数据
book_list = Book.objects.all()
# 定义空列表
res_list = []
# book_list是queryset对象不能直接序列化 可以通过for循环一个个拼接成列表套字典的形式
for book in book_list:
res_list.append({'name':book.name,'price':book.price})
return Response(res_list)
APIView源码分析
? ? ? ? APIView的作用和Django的View作用差不多,APIView继承了View所以执行as_view时先走到APIView这个类中通过APIView里的dispatch进行一层封装对request这个对象进行了改变添加了3大认证(认证、权限、频率)可以来看看它的源代码:
? 首先我们来看路由层,路由和View一样也是用了as_view()方法,但是我们在视图类中并没有写,所以用脚趾头想也知道了按住 command点击APIView中去查看
? 再次调用到View中的as_view,在上一篇中已经查看过View的源码所以现在和View中的一样再调用dispatch方法但是我们视图层中没有定义所以也要在父类中查看:
总结:
? ? ? ? 1.只要继承APIView都没有csrf的认证
? ? ? ? 2.视图类中使用的request变成了dif提供的Request类的对象
? ? ? ? 3.执行视图类的方法之前,执行了3大认证(认证、权限、频率)
? ? ? ? 4.在执行三大认证和视图类的方法过程中只要报错都会被捕获处理
Request类源码分析
? ? ? ? 视图类中使用的request对象已经变成了drf提供的Request类的对象了,request已经不是原来的request了那么它还能像原来的request一样使用吗我们来通过Request的源代码进行分析:
? 看了源代码可以知道和原来的request使用是一样的所以以后用的所有属性或方法直接用就可以
? 新的request内部有原生的request request._request
? data是个方法被property装饰了变成了数据属性用
? urlencoded、form-data、json无论哪种格式都从request.data中取
? 取文件依旧从request.FILES中取
? query_params:request.query_params 获取get请求提交的参数 等同于 request._request.GET与request.GET
序列化组件基本使用
? ? ? ? 序列化组件的使用类似于forms组件,也是定义一个序列化类然后序列化数据,比如获取book表中数据时:
'''新建一个py文件写序列化类'''
from .models import Book # 倒入book表
from rest_framework import serizlizers # 倒入需要继承的serializers
class BookSerializer(serizlizers.Serializer):
name = serializers.CharFiels()
price = serializers.CharField()
序列化写好后我们需要配路由然后在视图层来写具体功能获取表的多条数据
from rest_framework.view import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
class BookView(APIView):
def get(self, request):
book_list = Book.object.all()
ser = BookSerializer(instance=book_list, many=True)
# instance表示要序列化的数据,many=True表示序列化多条默认是False
return Response(ser.data)
获取表的单条数据,需要再穿个pk参数来指定
# 获取单条数据
class BookDetailView(APIView):
def get(self.request,pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book)
return Response(ser.data)
反序列化
? ? ? ? 将前端传过来的数据反序列化成我的对象然后存到数据库里面,如对book表进行新增、修改:
class Bookview(APIview):
def post(self,request):
# 将前端传入的数据从data中取出
ser = Bookserializer(data=request.data)
# 对数据进行校验
if ser.is_valid():
# 校验通过数据保存
ser.save()
return Response(ser.data)
else:
# 校验不通过返回错误信息
return Response(ser.errors)
class BookDetailView(APIView):
def put(self,request,pk):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
'''这样写会报错显示需要重写create方法和update方法'''
所有我们要在序列化类中再重写create方法,同理修改数据的时候也要重写一个update方法
'''新建一个py文件写序列化类'''
from .models import Book # 倒入book表
from rest_framework import serizlizers # 倒入需要继承的serializers
class BookSerializer(serizlizers.Serializer):
name = serializers.CharFiels()
price = serializers.CharField()
# 重写新增方法
def create(self,validated_data):
# validated_data是校验过后的数据
Book.objects.create(**validated_data)
return res
# 重写修改方法
def update(self, instance, validated_data):
# instance是要修改的数据
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.save()
return instance
|