一、什么是rest_framework
它是基于Django的,帮助我们快速开发符合RESTful规范的接口框架。
安装方式有很多种,可以通过pip,或者在pycharm中安装也可以 二、APIView
它的作用和from django.views import View中的View作用差不多,APIView是继承了View,所以执行as_view,dispatch方法都会
先走到APIView这个类中。所以通过这个APIView里的dispatch进行一层封装,对request这个对象进行改变,添加了认证、权限、频率这些
认证。可以去看看它的源码。
视图层(CBV模式): class Login(APIView):
路由层:url(r'login/',views.Login.as_views()) 分析:
程序启动时:会执行一遍django中的代码,函数没有被调用的话,只会检测其语法是否正确,看到路由层views.Login.as_views(),这是
一个函数加了括号,所以会执行到,as_views这是一个由类去调用并没有传参数的函数,如果不是静态方法,就是一个类方法,
我Login这个类中没有as_views这个方法,所以去它的基类(APIView)去找,找到了 as_view(cls,**initkwargs):
"""
Store the original class on the view function. This allows us to discover information about the view when we do URL
reverse lookups. Used for breadcrumb generation.
"""
if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
def force_evaluation():
raise RuntimeError(
'Do not evaluate the `.queryset` attribute directly, '
'as the result will be cached and reused between requests. '
'Use `.all()` or call `.get_queryset()` instead.'
)
cls.queryset._fetch_all = force_evaluation view = super(APIView, cls).as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs # Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view) # 这行代码 view = super(APIView, cls).as_view(**initkwargs),它会执行APIView基类(View)中的
as_view方法,得到一个函数的内存地址,赋值给view
最后return csrf_exempt(view) #csrf_exempt()是不是局部禁用了csrf检测
所以,在程序启动了之后,路由层的代码应该为url(r'login/',views.Login.csrf_exempt(view))
# 注意其实这里不是最终的版本,他还会执行csrf_exempt(view),总之views.Login.csrf_exempt(view)的执行结果是一个函数的内存地址
# csrf_exempt这个就是禁用掉csrf认证的装饰器吧,最后返回的还是view函数 有请求来的时候:
当有请求走到路由层时,那么该url对应的函数内存地址便会加括号直接运行,比如url为login,那么执行views.Login.view()
通过上面as_view方法,我们不难找到view方法,APIView中的view,是调用其父类(View)as_view方法,而as_view返回值就是view的内存地址,
那么view函数的源码就是下面这些,经过一些判断,最后返回的是dispatch方法的返回值
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs)
view函数的返回值return self.dispatch(request, *args, **kwargs),这里的self其实就是Login(这个视图类的对象),所以我们的查找
顺序为对象名称空间,然后就是它父类的名称空间,一层一层往上找,Login这个试图类是我们自己写的,如果自己没写dispatch方法的话,那应该就去
它的基类(APIView)去找dispatch,我们可以在APIView类中可以看到有这个dispatch方法,下面列出源码:
def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate? try:
self.initial(request, *args, **kwargs) # Get the appropriate handler method
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 dispatch方法主要看这几句:
-----------------------------------------------------------
request = self.initialize_request(request, *args, **kwargs)
-----------------------------------------------------------
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
response = handler(request, *args, **kwargs)
----------------------------------------------------------- ############
好下面来说说注意的第一行代码:request = self.initialize_request(request, *args, **kwargs)
############
# 我先说它做了什么事情,不看内部代码,将self(此时是Login视图类的对象),执行方法initialize_request方法的返回值赋值给了request,
# 其实这句代码就是重新封装了request,方法传入的request对象其实就是没有被处理过的,经过一顿操作后,返回值request就是rest_framework
# 中Request类的对象。下面是initialize_request方法的源码:
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
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就是rest_framework中的Request类了,括号里就是传过去的参数吧,这里self也是视图类
的对象(Login),拿一个括号里的参数来讲,其他参数方式都是一样,就不一一解释了。
比如这句:authenticators=self.get_authenticators()
这句代码不难理解吧,直接self的get_authenticators绑定方法,也可能是静态方法,把返回值赋值给authenticators,我这里说静态是光看这
一句代码可以看出。点进去看看get_authenticators源码如下:
def get_authenticators(self):
"""
Instantiates and returns the list of authenticators that this view can use.
"""
return [auth() for auth in self.authentication_classes]
最终返回的是一个列表,这里的self还是视图类对象(Login),authentication_classes这就是一个属性对吧,那么我们就去找找这个属性到底
是什么,self为视图类对象,那我们先从视图类(Login)找属性,我们自己写的视图类没有的话,就去继承的APIView类中查看。就在该类的最前面部分
有这样一段代码:authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES,那就继续按住ctrl,点击api_settings
去查看呗,这句代码api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS),api_settings它是APISettings这个类的对象,
你可以看到这个常量DEFAULTS,那么就在当前py文件搜索下,看看哪里出现过,最终肯定能找到,DEFAULTS它是一个字典,这个字典里就有很多key,
value形式,我们不难找到DEFAULT_AUTHENTICATION_CLASSES这个key对吧:
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
)
rest_framework.authentication.SessionAuthentication,这样的形式我们是不是见过(settings文件中有很多)
我们可以通过导模块的方式,看看这是什么。
from rest_framework.authentication import SessionAuthentication
可以看出,这是一个类,那么,我们倒着再理解下。注意:
api_settings.DEFAULT_AUTHENTICATION_CLASSES ---->>> 是一个元组(列表也是) == [类,类,类]
authentication_classes 这个属性也就是 ---->>> 是一个元组(列表也是) == [类,类,类]
回到最初那个地方 [auth() for auth in self.authentication_classes],列表生成式不难理解,那么get_authenticators方法返回的
就是[类(),类(),类()] ----->>> 也就是[对象,对象,对象],又回到Request对象的实例了
authenticators=self.get_authenticators(),所以authenticators就是一个[对象,对象,对象],就是装着对象的列表。 ######总结一下initialize_request这个方法:
1、它最终返回的就是一个Request的对象,这里的Request不再是之前那个了,是rest_framework里的Request对象
2、再看返回值这里,self.get_authenticators()最终得到是装着对象的列表,列表里的对象是视图类对象里的authentication_classes
这个属性得到的,而这个属性它是一个列表(元组也行),装着对应的类。 提醒几点:注意你看的源码,当前的self是谁,还有就是面向对象属性的查找顺序。(先对象名称空间,它父类的名称空间,父类继承基类的名称空间
,最后应该就是type吧(type这个的话,我理解是这样)) ############
那好继续下一句注意的代码,self.initial(request, *args, **kwargs)
############
这行代码self.initial(request, *args, **kwargs),它主要做了登陆验证,权限验证,频率验证,如果一个请求都满足上面这些这些验证的话,
那么就会执行到对应的请求方法里面,比如来一个get请求,那就走到该视图类get方法中去
下面是self.initial(request, *args, **kwargs)方法的源码
def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs) # Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg # Determine the API version, if versioning is in use.
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request) 这个方法里,需要注意的就是最后这三行代码,我先就说说它是做什么用的吧,后面我会再挨个挨个写
##注意啊,这里的request是rest_framework中的Request的对象
self.perform_authentication(request) ##它是进行登陆验证的
self.check_permissions(request) ##它是就行权限验证的
self.check_throttles(request) ##它是进行频率验证的 ############
好了,继续下面的代码:
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)
############
##注意啊,这里的request是rest_framework中的Request的对象
##很简单的if判断逻辑的代码,我说说大概意思吧,
request.method.lower() ---->> 本次请求方法的小写(get,post,put等等)
self.http_method_names ---->> 这里的self就是视图类对象,http_method_names就是一个列表,装着请求方法的小写
这是很基本的面向对象的属性查找,自己看查找看看,看看在哪个类里?
handler = getattr(self,A,B) ---->> 面向对象里的反射,如果在self中有A的话,那么handler就是A的内存地址,没有的话就是B的内存地址
response = handler(request, *args, **kwargs) --->> 最终会执行上面得到的函数内存地址,将返回值赋值给response 这里就举个例子,更加明白上面这几句代码。
浏览器发送一个login的get请求,那么request.method.lower()就是get,它在http_method_names这个列表里面,所以handler就是get方法的
内存地址(这里的get就是视图类里写的get方法),便会执行get这个方法,假如这个get方法的返回值是HttpResponse('login get'),
那么response就是HttpResponse('login get')。 再写一个注意的地方,回到dispatch这个方法,里面是不是有一个try....except捕捉异常的代码,它有什么用呢?这个跟进行登陆验证,权限验证,
频率验证那里有关系。后面写这个的时候,我会再写。 这部分就到此结束吧, 登陆验证,权限验证,频率验证 后面再写。
不能密密麻麻写一大推,然后会发生太长不看(我就是这样哈哈)
格式可能太差了,没办法,想到哪里写到哪里

rest_framework --- APIView的更多相关文章

  1. Django生命周期 URL ----> CBV 源码解析-------------- 及rest_framework APIView 源码流程解析

    一.一个请求来到Django 的生命周期   FBV 不讨论 CBV: 请求被代理转发到uwsgi: 开始Django的流程: 首先经过中间件process_request (session等) 然后 ...

  2. django rest_framework入门四-类视图APIView

    上节,我们使用函数视图,用了@api_view装饰器来修饰,这一节,我们介绍类视图APIView,显然,类视图更符合面向对象的原则. 1.使用类视图APIView重写API 类视图APIView,取代 ...

  3. 2 APIView与序列化组件

    1.入门 1.1 参考blog 官方文档:http://www.django-rest-framework.org/tutorial/quickstart/#quickstart yuan的Blog: ...

  4. Django - rest - framework - 上

    一.快速实例 http://www.django-rest-framework.org/tutorial/quickstart/#quickstart http://www.cnblogs.com/y ...

  5. 0801 RESTAPI设计,DRF 序列化

    1.内容回顾    1.restframework serializer(序列化)的简单使用                QuereySet([obj,obj,obj])  -->  JSON ...

  6. django framework插件类视图方法

    1.使用类视图APIView重写API 类视图APIView,取代@api_view装饰器,代码如下: from rest_framework import status from rest_fram ...

  7. Django框架rest_framework中APIView的as_view()源码解析、认证、权限、频率控制

    在上篇我们对Django原生View源码进行了局部解析:https://www.cnblogs.com/dongxixi/p/11130976.html 在前后端分离项目中前面我们也提到了各种认证需要 ...

  8. REST_FRAMEWORK加深记忆-三种CLASS VIEW的进化史

    一层一层的封装,又能到底层,就会有全局感啦... from rest_framework import status from rest_framework.response import Respo ...

  9. 源码怎么找之rest_framework的用户认证

    首先得有一点常识,比如用户认证,就是authenticate 比如一个函数,应该有返回值, 比如一个类里面的self,真的是代表本身这个类吗 再比如看到一个东西加括号,就两种情况,一种是函数,一种是类 ...

随机推荐

  1. js.css嵌入dll

    处理请求,返回 public ActionResult Get() { //传递一个部分名称 var n = Request["n"]; n = n.Replace('/', '. ...

  2. RestTemplate请求出现401错误

    最近遇到一个请求API接口总是报401 Unauthorized错误,起初是认为这个是平台返回的,后来用Postman请求,发现平台其实返回的是一串json,里面带有一些权限验证失败的消息,但到我们代 ...

  3. Scanners-Box:开源扫描器大全 2017-04-22

    Scanners-Box:开源扫描器大全 2017-04-22 Scanners-Box是一个集合github平台上的安全行业从业人员自研开源扫描器的仓库,包括子域名枚举.数据库漏洞扫描.弱口令或信息 ...

  4. centos解决The path "" is not a valid path to the 3.2.0-4-amd64 kernel headers.问题

    我的机子炸了,然后我就得重新装我的虚拟机,再然后我就想去弄好我的共享文件夹安装vmtools,安装的时候出现了一个问题,我忘记以前是怎么解决的,又困扰了我好久 Searching for a vali ...

  5. Python爬虫《Python网络爬虫相关基础概念》

    引入 之前在授课过程中,好多同学都问过我这样的一个问题:为什么要学习爬虫,学习爬虫能够为我们以后的发展带来那些好处?其实学习爬虫的原因和为我们以后发展带来的好处都是显而易见的,无论是从实际的应用还是从 ...

  6. 单链表的插入伪算法和用C语言创建单链表,并遍历

    非循环单链表插入结点伪算法讲解 q插入p之后的伪算法:第一种表示方法:r = p->pNext; // p->pNext表示的是所指向结点的指针域,指针域又是指向下一个结点的地址p-> ...

  7. Hadoop的安装与配置(虚拟机中的伪分布模式)

    1引言 hadoop如今已经成为大数据处理中不可缺少的关键技术,在如今大数据爆炸的时代,hadoop给我们处理海量数据提供了强有力的技术支撑.因此,了解hadoop的原理与应用方法是必要的技术知识. ...

  8. Java JSONArray的封装与解析

    package com.kigang.test; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import java.ut ...

  9. Tomcat 数据源的原理、配置、使用

    1.数据源的作用及操作原理 在程序代码中使用数据源是可以提升操作性能的,这种性能的提升依靠于运行的原理. 传统JDBC操作步骤 1.加载数据库驱动程序,数据库驱动程序通过CLASSPATH配置: 2. ...

  10. spring----对IoC和DI的理解

      学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和 ...