APIView执行流程(源码分析)、Request对象源码分析


一、APIView执行流程——源码分析(难,了解)

1.1 基于APIView+JsonResponse编写接口

# 原来基于django原生的View编写接口
# drf提供给咱们的一个类,以后使用drf写视图类,都是继承这个类及其子类,APIView本身就是继承了Django原生的View

class BookView(APIView):
    def get(self, request):
        books = Book.objects.all()
        book_list = []
        for book in books:
            book_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})

        return JsonResponse(book_list, safe=False)

1.2 基于APIView+Response 写接口

class BookView(APIView):
    def get(self, request):
        books = Book.objects.all()
        book_list = []
        for book in books:
            book_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})

        return Response(book_list)  # 无论是列表还是字典都可以序列化,同时也不需要JsonResponse的参数了

1.3 APIView的执行流程

路由中写的:

path('books/', views.BookView.as_view()),---》请求来了,执行views.BookView.as_view()()----->现在的as_view是APIView的as_view(因为我们把父类从View换成了APIView)

我们点进源码查看可以发现APIView其实继承了View

class APIView(View):

往下查找as_view()的代码

# APIView的as_view方法:view还是原来的view,但是以后再也没有csrf认证了
 	@classmethod
   	def as_view(cls, **initkwargs):
        # 调用父类的as_view,父类是django原生的View
        # 把djagno原生View的as_view方法中的闭包函数view拿出来了
        view = super().as_view(**initkwargs)
        # csrf_exempt 排除所有csrf的认证
        # 相当于在所有的方法上面加了这个装饰器
        return csrf_exempt(view)
'从他内部的view我们可以看到他是用派生方法调用父类View中的as_view因此我们说view还是原来的view,但是返回的结果是csrf_exempt(view),回顾装饰器的知识,我们可以知道虽然我们把装饰器写成了语法糖,但是在运行的时候其实就是把被装饰的函数名称传进来当参数运行,因此这里就是取消了csrf认证的作用'
# 路由匹配成功,执行的其实就是 csrf_exempt(view)(requets)--->而这个view就是View的as_view中的闭包函数view---》然后执行self.dispatch---->self是视图类的对象---》BookiView产生的对象---》这时候会执行self.dispatch,根据名称的查找顺序他会查找到APIView的dispatch:
    def dispatch(self, request, *args, **kwargs):
        # 这里的参数中的request是django原生的request,老的request
        # 把老的request包装成了新的request,这个是drf提供的Request类的对象
        request = self.initialize_request(request, *args, **kwargs)
        # 到此以后,这个request就是新的了,老的request在哪?
        # request._request 这是老的
        
        # 把新的request放到了self对象【BookView的对象】
        self.request = request
        try:
            # 执行了三大认证【认证,频率,权限】,使用新的request,之后会将
            self.initial(request, *args, **kwargs)
            
            # 跟之前一毛一样用反射获取执行结果,如果报错就用异常捕获处理
            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
			# 把新的request传入了,视图类的方法中get的request也是新的
            response = handler(request, *args, **kwargs)

        except Exception as exc:
            # 在执行3大认证和视图类中方法的过程中,如果出了异常,都能捕获到---》全局异常捕获
            response = self.handle_exception(exc)
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
    
    
    
'上方的request调用了initialize_request方法,这个方法的返回结果产生了一个Request生成的对象,它的源码如下:'
        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
        )
'接着我们点进这个Request类的源码,我们会发现老的request变成了_request属性'

    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        self._request = request
        self.parsers = parsers or ()
        self.authenticators = authenticators or ()
        self.negotiator = negotiator or self._default_negotiator()
        self.parser_context = parser_context
        self._data = Empty
        self._files = Empty
        self._full_data = Empty
        self._content_type = Empty
        self._stream = Empty

    
# 总结:APIView的执行流程
	1 去除了所有的csrf
    2 包装了新的request,以后在视图类中用的request是新的request  Request类的对象,不是原生的了
    	-原生的在:新的requets._request
    3 在执行视图类的方法之前,执行了3大认证
    4 如果在3大认证或视图函数方法执行过程中出了错,会有异常捕获----》全局异常捕获
    5 以后视图类方法中的request都是新的了
    
    
    
    


    
    
# 补充:装饰器的基本原来

def auth()  # 装饰器

def add()   # 函数

# 使用auth装饰add函数
@auth   #  本质是  add=auth(add)
def add()

# 以后再使用add,其实就是在使用 auth(add)  的返回结果

二、Request对象源码分析(难,了解)

新的Request---》区别于老的

老的:由django.core.handlers.wsgi.WSGIRequest 产生

新的:由from rest_framework.request import Request产生

	-request现在是新的 request._request  获取到的是老的

通过查看源码我们发现他内部并没有我们常用的一些方法,如:method,但是我们在调用的时候缺可以跟之前一样使用,这时候我们发现了他内部有一个双下getattr的魔法方法(查找属性或方法不存在的时候会触发他),那我们根据目前学的知识,最可能是这里有玄机,点击来查看源码:

# Request源码
	-方法 __getattr__
    	-在视图类的方法中,执行request.method ,新的request是没有method的,就触发了新的Request的__getattr__方法的执行
        def __getattr__(self, attr):
            try:
                # 从老的request中反射出 要取得属性
                return getattr(self._request, attr)
            except AttributeError:
                return self.__getattribute__(attr)
    
    
'接着我们发现下面有很多用伪装的语法糖装饰的函数,这样调用方法的时候可以伪装成数据,目前我们只需要了解作用,后面会详细讲解'

    -request.data--->这是个方法,包装成了数据属性
    	-以后无论post,put。。放在body中提交的数据,都从request.data中取,取出来就是字典
        -无论是那种编码格式
        
        
    -request.query_params--->这是个方法,包装成了数据属性
    	-request.GET请求携带的参数,以后从这里面取
        -query_params:查询参数--->restful规范请求地址中带查询参数
        
        
    -request.FILES--->这是个方法,包装成了数据属性
    	-前端提交过来的文件,从这里取
    
    
    
    
    

 # Request类总结
	-1  新的request用起来,跟之前一模一样,因为新的取不到,会取老的__getattr__
    -2 request.data  无论什么编码,什么请求方式,只要是body中的数据,就从这里取,字典
    -3 request.query_params 就是原来的request._request.GET
    -4 上传的文件从request.FILES
    
    
    
    
    
# python 中有很多魔法方法,在类中,某种情况下触发,会自动执行
	-__str__:打印对象会调用
    -__init__:类() 会调用
    -__call__: 对象() 会调用
    -__new__:
	-__getattr__:对象.属性,如果属性不存在,会触发它的执行


posted @   致丶幻  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
  1. 1 So Far Away (Acoustic) Adam Christopher
  2. 2 雪 Distance Capper&罗言RollFlash
  3. 3 CollapsingWorld
  4. 4 Call You Tonight Johnta Austin
So Far Away (Acoustic) - Adam Christopher
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作曲 : David Guetta/Giorgio H Tuinfort/Jamie Scott/Martijn G Garritsen

Light ‘em up, light ‘em up

Tell me where you are, tell me where you are

The summer nights, the bright lights

And the shooting stars, they break my heart

I‘m calling you now, but you‘re not picking up

Your shadows so close if you are still in love

Then light a match, light a match

Baby, in the dark, show me where you are

Oh, love

How I miss you every single day when I see you on those streets

Oh, love

Tell me there‘s a river I can swim that will bring you back to me

‘Cause I don‘t know how to love someone else

I don‘t know how to forget your face

Oh, love

God, I miss you every single day and now you‘re so far away

It‘s breaking me, I‘m losing you

We were far from perfect, but we were worth it

Too many fights, and we cried, but never said we‘re sorry

Stop saying you love me

You‘re calling me now, but I can‘t pick up

Your shadow‘s too close, and I‘m still in love

The summer‘s over now, but somehow, it still breaks my heart

We could have had the stars, oh

Oh, love

How I miss you every single day when I see you on those streets

Oh, love

Tell me there‘s a river I can swim that will bring you back to me

‘Cause I don‘t know how to love someone else

I don‘t know how to forget your face

Oh, love

God, I miss you every single day and now you‘re so far away

Oh, love

How I miss you every single day when I see you on those streets

Oh, love

Tell me there‘s a river I can swim that will bring you back to me

‘Cause I don‘t know how to love someone else

I don‘t know how to forget your face

Oh, love

God, I miss you every single day when you‘re so far away

点击右上角即可分享
微信分享提示