一,什么是restframework?
restframework是基于Djiango的一套REST框架。
二,查看源码储备知识点:
1,Djiango的CBV与FBV模式
2,python的多继承属性查找顺序
FBV模式:
FBV就是基于函数来处理请求的视图方法(function based view) ,优点就是比较简单,通俗易懂,一般来说都是使用这种方法,这里我就不多加介绍了
CBV模式:
CBV是基于python的面向对象类方法来处理的视图方法(class based view),优点:提高了代码的复用性,可以使用面向对象的方法,提高了代码的可维护性,
一种请求对应一种属性方法。这里我们着重来了解这种方式。
三,Djiango的CBV模式:
如果前端服务器发送一个GET请求,使用FBV模式的话view视图就是这样写:
from django.http import HttpResponse def my_view(request): if request.method == 'GET': return HttpResponse('OK')
使用CBV的话,就是这样写:
from django.http import HttpResponse from django.views import View class MyView(View): def get(self, request): return HttpResponse('OK')
路由url,FBV的写法为:
from django.conf.urls import url from django.contrib import admin from stark.service.stark import site from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^stark/', site.urls), url(r'^login/', views.login), url(r'^index/', views.index), url(r'^logout/', views.logout), ]
CBV的写法为:
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^ret/', views.Get_ret.as_view()), #CBV类型的路由 ]
Django的url是将一个请求分配给可调用的函数的,而不是一个class。针对这个问题,class-based view提供了一个as_view()
静态方法(也就是类方法),调用这个方法,会创建一个类的实例,然后通过实例调用dispatch()
方法,dispatch()
方法会根据request的method的不同调用相应的方法来处理request(如get()
, post()
等)。到这里,这些方法和function-based view差不多了,要接收request,得到一个response返回。如果方法没有定义,会抛出HttpResponseNotAllowed异常。
例:
写一个基于CBV的视图:
class LoginView(View): def get(self,request): return render(request,"login.html") def post(self,request): user=request.POST.get("user") pwd=request.POST.get("pwd") if 1: return HttpResponse("OK")
再对应写一个处理的url:
url(r'^login/', views.LoginView.as_view()),
通过面向对象的继承,我们发现as_view()其实是父类View下的方法,通过查看源码我们可以发现:
1,第一步:
2,第二步:
3,第三步:
通过查看View源码我们可以的看出,CBV的路由分配方法是,首先调用View下的as_view方法,返回一个view的执行结果,view的执行结果取决与as_view下的一个dispatch的执行结果,
dispatch的内部是做了一个请求判断,再通过反射调用我们定义 LoginView(View) 下的请求方法执行,把结果返回。
这样我们就可以把之前写的的url理解为:
# url(r'^login/', views.LoginView.as_view()), # url(r'^login/', View.as_view()), # url(r'^login/', View.view), 最后其实就是在调用View的view方法
这里我们需要理解python多继承关系的查找顺序,已经面向对象的类方法。有了对CBV模式的理解,接下来我们正式来看restframework框架源码。
四,restframework初步了解。
我们把restframework分为以下几个部分来分解:
(1) APIView
(2) 序列化组件
(3) 视图组件
(4) 解析器
(5) 认证组件
(6) 权限组件
(7) 频率组件
(8) 分页器
(9) 响应器
(10) url控制器
(11) 版本控制
1,首先我们来查看APIView:
类似的在view文件中,我们先要定义一个类来处理相关的请求:
from rest_framework.views import APIView class PublishView(APIView): def get(self,request): publish_list=Publish.objects.all() ret=serialize("json",publish_list) return HttpResponse(ret) def post(self,request): pass
路由文件中的url:
url(r'^publishes/', views.PublishView.as_view()),
这里唯一的区别是视图文件中我们定义的类是继承的APIView,而不是View,但是我们去查看APIView源码发现其实APIView是继承View的,这就表明到最后我们还是继承了View。
根据之前的经验,我们首先从url里的as_view()入手,发现APIView里有一个as_view方法属性,根据面向对象继承的属性查找顺序,这个as_view方法是调用的APIView里的。
看源码可以看出,这个as_view()方法最后返回的是view,而view是在调用父类的也就是APIView父类View的as_view()方法,而我们知道View中的as_view()方法的返回结果取决于dispatch()方法的执行结果。
根据继承的属性,这里的 self ,我们必须要注意的是这个dispatch()方法并不是View的dispatch()方法而是APIView的dispatch()方法。只有当View没有这个方法时才会调用View下的dispatch()方法,很不幸,APIView刚好有这个方法,看源码可以看出这个方法最后也是利用反射来调用我们定义类下面的请求方法,只不过是加了一些逻辑。
最后我们可以这样看路由文件中url:
#url(r'^publishes/', views.PublishView.as_view()), #url(r'^publishes/', APIView.as_view()), #url(r'^publishes/', APIView.as_view()), #url(r'^publishes/', View.view), 分解到最后
源码部分我们抛去一些逻辑部分,也可以大致分解成:
用户一旦访问get请求 View.view(request): return self.dispatch(request, *args, **kwargs) ---- APIView.dispatch(request, *args, **kwargs): if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower()) response = handler(request, *args, **kwargs) return response 最后返回一个response
查看了这两个源码可以看出,rest framework框架的请求方式跟CBV的方式基本一样,只是在它的基础上加了很多逻辑判断,其根本上还是属于CBV模式。
初次看源码心得:
1,要一层层的剥离,循循渐进,看核心部分
2,要注意里面self是指的谁,不可主观臆断。