前言
#在CBV中,知道,分发函数的任务是在dispatch,(view中的方法) #这里APIview继承了view,但其重写了dispatch方法,
一、什么是drf
#drf(django rest framework)框架(django的app) #安装: djangorestframework #它是一个app,所以需要在settings中注册
‘rest_framework’ 只是快速的构建resful规范的接口 csrf_exempt:局部禁用csrf(csrf是可以局部使用,局部禁用) #drf可以注释csrf 以后再执行的dispatch方法是APIView的dispatch方法 getattr和setattr #重点掌握这三点: request.data 是个方法,包装成了属性,前台传过来body体中数据的数据,放在里面 request.query_params 这个是原来GET中的数据 request把原来的request包装进去了
from django.views.decorators.csrf import csrf_exempt,csrf_protect
csrf_exempt局部禁用
csrf_protect局部使用
from rest_framework.views import APIView class Books(APIView): # 现在这个request对象,已经不是原来django中的request对象了,它是rest_framework.request下的Request def put(self, request, pk): # 原来的request是:request._request print(request._request.GET) #按理说可以这样取值 print(request.GET) # 为什么这样也能取出来(method,GET,POST,BODY) print(request.data) # 如果前端传过来的编码格式:json格式:{'name': '西游记', 'price': '15'} #如果前端传过来的编码格式:urlencoded格式:<QueryDict: {'name': ['红楼梦'], 'price': ['15']}> # request.data是谁的对象? # request.data不同编码格式过来,它可能是不同类的对象,但是用法是一样的
# class Student(): # name='pdun' # # def __init__(self,age): # self.age=age # # s1=Student(1) # print(s1.name) # print(s1.age) # print(s1.sex) #想赋值,只能重写__setattr__方法 class Student(): name='pdun' def __init__(self,age): self.age=age def __getattr__(self, item): #通过点取值,会走到这里 return '没有这个属性' def __setattr__(self, key, value): #通过点赋值,会走到这里 pass def __getitem__(self, item): #通过中括号取值,会走到这里 pass def __setitem__(self, key, value): #通过中括号赋值,会走到这里 pass s1=Student(1) s1.sex='man' print(s1.sex)
#此时点API进去读源码 class APIView(View): #继承了View @classmethod def as_view(cls, **initkwargs): #重写了as_view的方法 #执行父类的as_view方法,拿到view的内存地址, view = super(APIView, cls).as_view(**initkwargs) #把原来的view.cls替换为现在的 view.cls = cls view.initkwargs = initkwargs #这一步相当于给view添加了一个装饰器, return csrf_exempt(view) #局部禁用csrf ,相当于给view加了一个装饰器 #view方法最终执行的是disdispatch,而API中有自己的dispatch #此时来到APIview中的dispatch方法 def dispatch(self, request, *args, **kwargs): self.args = args self.kwargs = kwargs #简单的赋值 #此时后边(括号内)request是原来的request, #经过initialize_request处理后,不再是request request = self.initialize_request(request, *args, **kwargs) self.request = request #执行后的赋值 self.headers = self.default_response_headers #此时点initialize_request进去 def initialize_request(self, request, *args, **kwargs): parser_context = self.get_parser_context(request) #类实例化产生对象,产生这个Request对象,是drf的request return Request( request, #原来的request包含在drf的request之内 # 解析用的 parsers=self.get_parsers(), #认证用的 authenticators=self.get_authenticators(), # 分页用的 negotiator=self.get_content_negotiator(), #解析用 parser_context=parser_context ) #此时点Request进去 (from rest_framework.request import Request点这也可以) class Request(object): self._request = request #原来的request变成_request #所以在外界可以request._request拿到原来的 #这就是为什么_request.GET和request.GET都能取到值的原因 def __getattr__(self, attr): try: #通过反射,去原来的request中拿出要取的属性(如:GET,POST...) return getattr(self._request, attr) except AttributeError: return self.__getattribute__(attr) #request.query_params 这个是原来GET中的数据 @property def query_params(self): return self._request.GET #request.data 是个方法,包装成了属性,前台传过来body体中数据的数据,放在里面 @property def data(self): if not _hasattr(self, '_full_data'): self._load_data_and_files() return self._full_data
重点掌握
#request.data 是个方法,包装成了属性,前台传过来body体中数据的数据,放在里面 #request.query_params 这个是原来GET中的数据 #request把原来的request包装进去了 包装成了_request,方便读源码