drf源码解析(二)

drf源码解析(二)

本博客默认读者有过django学习基础,了解django基本运行方式。

4,request

4.1 面向对象的一点知识

4.1.1获取对象的成员的函数方法

先来看一个关于面向对象的知识点,在这里我们创建一个类Foo,通过__init__方法赋值:

class Foo(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b


obj = Foo(1, 2)
print(obj.a) #1
print(obj.b) #2

那么不出意外的,上面代码会输出a和b的值。

其实在获取对象成员时,默认会调用 __getattribute__方法,如果我们没有自己定义这个方法,就回去父类object里面去找。

class Foo(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def __getattribute__(self, item):
        print("调用了__getattribute__方法,获取到了:",item)
        return super().__getattribute__(item)


obj = Foo(1, 2)
print(obj.a)
print(obj.b)

输出以下结果:

drf源码解析(二)_第1张图片

注意:如果获取对象中没有的成员,会报错,如

print(obj.c)
#AttributeError: 'Foo' object has no attribute 'c'

如果想要获取对象中不存在的成员,则可以通过定义 __getattr__实现,例如:

class Foo(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def __getattribute__(self, item):
        print("调用了__getattribute__方法,获取到了:",item)
        return super().__getattribute__(item)

    def __getattr__(self, item):
        print("调用了__getattribute__方法,获取到了:",item)
        return 123


obj = Foo(1, 2)
print(obj.a)
print(obj.b)
print(obj.c)

会输出以下结果

drf源码解析(二)_第2张图片

根据输出打印的顺序,我们可以看出,当访问对象中的成员时:

  • 先执行自己的 __getattribute__

  • 再执行父类的__getattribute__

    • 是自己成员,直接获取并返回

    • 不是自己成员,调用__getattr__,返回的值赋值给该成员

也就是说假如你通过__getattr__访问一个不存在的成员,return的值将会赋值给该成员。

4.1.2对象封装

定义一个类Base,并实例化一个对象base,再定义一个类Foo,实例化一个对象obj,在obj中封装base:

class Base(object):
    def v1(self):
        print("这是Base的v1")
    def v2(self):
        print("这是Base的v2")

class Foo(object):
    def __init__(self,a,b):
        self.a=a
        self.b=b

base=Base()

obj=Foo(base,10)

obj.a.v1()#这是Base的v1
obj.a.v2()#这是Base的v2

在实例化Foo这个类时,我们调用了init方法,将对象base作为参数传给了obj的成员a,这样base就封装在了obj中,obj就可以调用base中的方法,获取它的成员。

4.2drf中对request的封装

我们先来写一个简单的视图关系。

urls.py中定义路由:

#urls.py
from django.urls import path
from app01.views import view

urlpatterns = [

    path('user/', view.UserView.as_view()), 

]

在这里我们可以’ctrl’+鼠标左键 产看as_view的源码,在这里我复制了一部分比较重要的。

#views.py(drf)
class APIView(View):
    def as_view(cls, **initkwargs):
		
        #父类的as_view方法
        view = super().as_view(**initkwargs)
        view.cls = cls
        view.initkwargs = initkwargs
        
        return csrf_exempt(view)

as_view是APIView类的一个成员方法,而APIView类是继承View这个类的,值得一提的是,View这个类是django的源代码中定义在base.py的一个类。在as_view的第6行代码中,我们发现调用了父类的as_view方法并把返回值赋值给了view,下面我们来看看django中as_view的源代码,同样的我只截取了一部分方便理解。

#base.py(django)
class View:
    def as_view(cls, **initkwargs):
        def view(request, *args, **kwargs):
			
            return self.dispatch(request, *args, **kwargs)

        return view

在这里我们重点关注函数的参数和返回值,在view方法中,调用了dispatch方法对request和其他参数进行操作,并将结果返回,那么我们继续看看dispatch,注意,调用成员函数方法时,会先找自身有没有这个函数,如果有就用自己的,没有才会去父类找,而在drf的views.py中就有对dispatch的定义。

#views.py(drf)
class APIView(View):
    def dispatch(self, request, *args, **kwargs):
		
        #新的requst
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request      
   
        self.initial(request, *args, **kwargs)

		
        #反射执行getattr方法,并传到新的request里面
        handler = getattr(self, request.method.lower(),self.http_method_not_allowed)

        response = handler(request, *args, **kwargs)

        return self.response

源码中对dispatch的解释是“这里的dispatch和django的dispatch很像”,而django中的dispatch的作用是

# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.

翻译过来大概就是“尝试去反射给正确的方法(函数),如果这个方法不存在就报错”,也就是说这个dispatch的作用是将request反射给正确的函数方法的。是不是有点像快递小哥,每个快递小哥都有自己负责的一片区域,收到一个包裹就送到指定的地方,要是收到不是自己负责区域的包裹就报错不干了。

注意在上面的代码中的第四行,调用了initialize_request方法对request进行了操作,你看着initalize这个单词是不是感觉要对request进行一种类似初始化的操作啊,那么前面讲了这么一大堆终于讲到今天的主题了。

下面我们来看看initialize_request这个函数

##views.py(drf)
class APIView(View):
    def initialize_request(self, request, *args, **kwargs):
        parser_context = self.get_parser_context(request)

        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )

到这里我们终于发现了,drf对request进行了这样的封装操作,把原有的requst请求和其他的参数一起封装成了一个新的Request对象,并且返回给了原来的request,具体封装了些什么内容呢,来看看Request这个类是怎么构成的。

class Request:


    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
	
    def __getattr__(self, attr):
        try:
            return getattr(self._request, attr)
        except AttributeError:
            return self.__getattribute__(attr)

到这里还没完,我们继续来看看这个dispatch。

 handler = getattr(self, request.method.lower(),self.http_method_not_allowed)

这里调用了我们前面铺垫的getattr函数, 反射执行get方法,获得各种参数,并传到新的request里面。

drf源码解析(二)_第3张图片

后面我们会来分析一下认证,权限,限流三种组件,通过源码+案例的方式进行讲解。

你可能感兴趣的:(python之路,sqlite,数据库)