一、什么是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. Thrift笔记(三)--Thrift框架通信源码分析

    Thrift 客户端调用RPC的Demo public static void main(String[] args) throws Exception { TTransport transport ...

  2. 在asp.net中如何使用Session

    2.那么在asp.net中到底该怎么使用Session呢? Session对象用于存储从一个用户开始访问某个特定的aspx的页面起,到用户离开为止,特定的用户会话所需要的信息.用户在应用程序的页面切换 ...

  3. Android 自定义View之自绘控件

    首先要提前声明一下,我对于自定义View的理解并不是很深,最近啃了几天guolin博主写的关于自定义View的博客,讲的非常棒,只不过涉及到源码和底层的一些东西,我自己就懵逼了,目前只是会了关于自定义 ...

  4. EPS 转 pdf 在线

    EPS 转 pdf 在线网站 https://convertio.co/zh/eps-pdf/

  5. OpenSUSE 内核编译教程 (kernel 2.6.x)

    http://cn.opensuse.org/OpenSUSE_%E5%86%85%E6%A0%B8%E7%BC%96%E8%AF%91%E6%95%99%E7%A8%8B_(kernel_2.6.x ...

  6. XP环境安装request包报错:离线安装packages: certifi urllib3 idna chardet

    分别下载 request certifi urllib3 idna chardet 安装包 数据包下载地址:https://pypi.org/ 解压到python安装目录 使用cmd命令进入..\py ...

  7. 【Spring实战】—— 8 自动装配

    本篇介绍一下自动装配的知识,Spring为了简化配置文件的编写.采用自动装配方式,自动的装载需要的bean. 自动装配 有以下几种方式: 1 byName 通过id的名字与属性的名字进行判断,要保证B ...

  8. 作为软件技术人员建立自己的git账户并保存资料的重要性

    日常生活中,当修改并保存了一个文件,所得到的就是此文件的最新版本,假若今后因某一问题需要用到原来文件,可是很多情况下,这种修改是不可逆的.你修改完之后,无法回到你修改前的样子.为了避免这种情况,有的人 ...

  9. Bootstrap Table的使用小结

    1.Jquery中的一些东西学习一下子,补充完善一下,毕竟有些时候没有使用到 这个方式很有用,在使用bootstrap table的时候,选择当前已经选择的节点的事件中的ID的值 当前rows中有很多 ...

  10. 多层感知机训练minist数据集

    MLP .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1p ...