1.APIView基本使用
1.1 使用View+JsonResponse写
class BookView(View): def get(self, request): book_list = Book.objects.all() res_list = [] for book in book_list: res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish}) return JsonResponse(res_list,safe=False,json_dumps_params={'ensure_ascii':False}) # 只能序列化字典和列表,
1.2 使用APIView+drf的Response写
from rest_framework.views import APIView from rest_framework.response import Response from .models import Book class BookView(APIView): def get(self, request): # 此时这个request不是原来的那个request,而是一个新的request,具体请看下面request类源码分析
print(type(request._request) res = Book.objects.all() list_res = [] for i in res: list_res.append({'name' : i.name, 'price' : i.price, 'publish' : i.publish}) return Response(list_res)
2.APIView的源码分析
# 视图类继承APIView后,执行流程就发生了变化,这个变化就是整个的drf的执行流程 # 一旦继承了APIView入口 -路由配置跟之前继承View是一样的----》找视图类的as_view---》【APIView的as_view】 @classmethod def as_view(cls, **initkwargs): # 又调用了父类(View)的as_view view = super().as_vi ew(**initkwargs) ''' # 从此以后,所有的请求都没有csrf的校验了 # 在函数上加装饰器 @csrf_exempt def index(request): pass 本质等同于 index=csrf_exempt(index) ''' return csrf_exempt(view) -请求来了,路由匹配成功会执行 View类的的as_view类方法内的view闭包函数(但是没有了csrf认证), -真正的执行,执行self.dispatch---->APIView的dispatch 【这是重点】 def dispatch(self, request, *args, **kwargs): # 参数的request是原来的django原生的request # 下面的request,变成了drf提供的Request类的对象---》return Request(。。。) request = self.initialize_request(request, *args, **kwargs) # self 是视图类的对象,视图类对象.request=request 新的request self.request = request try: # 执行了认证,频率,权限 [不读] self.initial(request, *args, **kwargs) # 原来的View的dispatch的东西 if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) except Exception as exc: # 如果出了异常,捕获异常,处理异常,正常返回 # 在执行三大认证和视图类中方法过程中,如果出了异常,是能被捕获并处理的---》全局异常的处理 response = self.handle_exception(exc) self.response = self.finalize_response(request, response, *args, **kwargs) return self.response
总的来说就是只要用了APIView就不会有scrf认证,request就变成了drf中的request(例如1.2中的那个request,具体了解请看request类源码分析),执行视图类的方法之前,执行了3大认证(认证,权限,频率),在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理。
3.Requset类源码分析
#1 视图类中使用的request对象,已经变成了drf提供的Request类的对象了 -原生djagno 的request是这个类的对象:django.core.handlers.wsgi.WSGIRequest -drf的request是这个类的对象:rest_framework.request.Request #2 request已经不是原来的request了,还能像原来的request一样使用吗? -用起来,像之前一样 print(request.method) # get print(request.path) # /books/ print(request.GET) # 原来的get请求提交的参数 print(request.POST) # 原来post请求提交的参数 #3 Request的源码分析:rest_framework.request.Request -类中有个魔法方法:__getattr__ 对象.属性,属性不存在会触发它的执行 def __getattr__(self, attr): # 如果取的属性不存在会去原生django的request对象中取出来 try: #反射:根据字符串获取属性或方法,self._request 是原来的request return getattr(self._request, attr) except AttributeError: return self.__getattribute__(attr) -以后用的所有属性或方法,直接用就可以了---》(通过反射去原来的request中取的) -新的request内部有个老的request,就是 request._request -data 是个方法,被property装饰了,变成了数据属性用 -以后body体中提交的数据,都从这里取(request.POST) -urlencoded,form-data:提交的数据在request.POST中 -json格式提交的数据,在requets.POST中没有,它在request.body中 -现在无论那种格式,都从request.data中取 -query_params:get请求提交的参数,等同于request._request.GET 或 request.GET -其他:取文件也是从request.FILES中取,跟之前一样 # 验证 原生requets.POST 只有urlencoded和form-data格式提交的数据,json格式提交的数据在body中,拿出来自己处理,但是drf的request中有个data,data中可以取到任意编码提交的数据 # request.data 有时候是(urlencoded,form-data)QueryDict,有时候(json)是字典 # 4 什么是魔法方法? 1 在类中只要以__开头,__结尾的都称之为魔法方法 2 这种方法不需要手动调用,某种情况会自动触发 3 你学过的: __init__,__str__,__call__,......
4.序列化组件的基本使用
models中
from rest_framework import serializers class BookSerializer(serializers.Serializer): name = serializers.CharField() publish = serializers.CharField()
class BookView(APIView): def get(self, request): book_list = Book.objects.all() #instance是qs对象,一定要传many=True ser = BookSerializer(instance=book_list, many=True) return Response(ser.data)
class BookDetailView(APIView): def get(self, request, pk): book = Book.objects.filter(pk=pk).first() ser = BookSerializer(instance=book) return Response(ser.data)
5.反序列化
增加修改
标签:__,APIView,self,request,list,源码,序列化,book From: https://www.cnblogs.com/shangxin-bai/p/16731954.html