1、django restframework 请求流程源码剖析python
上面的认证一个流程是rest_framework的关于APIauth的认证流程,,这个流程试用权限、频率、版本、认证、这个四个组件都是经过类似的流程进行实现,不一样的组件,是在initial()这个方法中调用不一样的方法来进行执行的,同时在剖析源码的过程当中,咱们整个rest_framework总共分为10个组件,每一中组件均可以进行全局配置,和局部配置,下面依次介绍这10个组件。django
一、认证auth()json
上面流程已经提到,API认证,每个认证类的,真正的验证是执行了一个authenticate()方法,在自定义认证类时,须要重写这个authenticate()方法便可。同时,rest——framework提供了几个认证类from rest_framework.authentication 能够经过查看提供的认证类,在自定制时,能够继承这个里面的基类。后端
而authenticate()方法的返回值,一共有三种,第一种,认证不经过报错。第二种认证经过返回一个元组,元组中的内容是user对象和token对象。第三种是None,默认就是匿名用户api
from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication from django.http import JsonResponse from app01 import models import time ,hashlib class MyAuthtication(BaseAuthentication): '''用户api验证''' def authenticate(self ,request): token = request.GET.get('token') token_obj = models.Token.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed('用户认证失败') return ( token_obj.user, token_obj) def authenticate_header(self ,request): pass
from rest_framework import exceptions 关于说到的若是认证失败,须要报错,reset_framework是要返回指定报错的
raise exceptions.AuthenticationFailed ,这个主动触发这个AuthenticationFailed,报错,默认超类中会抓取这个异常,response返回。
全局配置和局部配置缓存
全局app
REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES':['app01.utils.auth.MyAuthtication',], 'UNAUTHENTICATED_USER':lambda:None} 一、在settings文件中 ,按照上述配置,认证类是能够有多个的,因此DEFAULT_AUTHENTICATION_CLASSES,这个key对应的是一个列表。 app01.utils.auth是认证类的路径。 二、关于咱们说认证返回有三种结果,若是是未登陆用户是,返回的信息是None,这个也能够进行定制,返回指定的信息,按照第二行配置
局部配置 前后端分离
class AuthView(APIView): authentication_classes = [BasicAuthentication,] 在视图中按照上面配置便可
二、权限(permission)post
2.1权限的是经过 此方法进行判断的 ,在重写的时候,重写这个has_premission方法便可,固然rest_framework,提供了几个默认的权限类供使用,from rest_framework.permissions ,经过这个permissions 文件查找几种提供的权限类,重写时能够继承。url
def check_permissions(self, request): """ Check if the request should be permitted. Raises an appropriate exception if the request is not permitted. """ for permission in self.get_permissions(): if not permission.has_permission(request, self): self.permission_denied( request, message=getattr(permission, 'message', None) )
has_premission()方法 。而这方法的返回值,一种是True,带表有权限,False表明没有权限。
2.2全局配置和局部配置
全局配置
REST_FRAMEWORK ={ 'DEFAULT_PERMISSION_CLASSES':['app01.utils.auth.MyPremission']}
局部配置
from rest_framework.permissions import BasePermission class AuthView(APIView): permission_classes = [BasePermission,]
三、频率(throttle)
3.1这个组件又称之为节流,这个做用就是现实一个api,在一个固定时间段内可以访问几回 , 是调用了每个节流类的allow_request方法进行判断的。这个能够重写也能够直接调用rest_framework提供的,从
from rest_framework.throttling 获取,里面的总体实现原理是相似的。同时这个地方要注意,咱们是以ip地址仍是用户来识别是不是同一个用户的,若是是匿名用户就能够用ip地址,若是是登陆用户能够用用户名或者用户id均可以。可是本质上,是没法真正实现这个限制访问的。
def check_throttles(self, request): """ Check if request should be throttled. Raises an appropriate exception if the request is throttled. """ for throttle in self.get_throttles(): if not throttle.allow_request(request, self): self.throttled(request, throttle.wait())
allow_request()方法返回两个结果,一个是True,表明有权限,一个是False,没有权限。
3.2所有和局部配置
全局
REST_FRAMEWORK ={DEFAULT_THROTTLE_RATES':{'all':'3/m'},
DEFAULT_THROTTLE_CLASSES:['app01.utils.auth.MyPremission']
}
关于这个节流的配置 ,后面的scope是说的是实际设置的默认频率,是每分钟3次的意思,能够看源码,这个单位不止分钟。 关于这个scope是须要在自定义的节流类中配置的。 通常使用这个SimpleRateThrottle就够用了
class VisitorThrottle(SimpleRateThrottle):
scope = 'all'
def get_cache_key(self, request, view):
'''这个就是返回一个放在django缓存中的key,
能够根据用户id,或者ip地址来而后返回这个ip这个字符串,
或者用用户id'''
return ip或者用户id
局部
class AuthView(APIView): throttle_classes = [] 将本身写的自定制的类导入,放到这个列表中便可
四、版本(version)
4.1版本认证是经过这个方法实现的
def determine_version(self, request, *args, **kwargs): """ If versioning is being used, then determine any API version for the incoming request. Returns a two-tuple of (version, versioning_scheme) """ if self.versioning_class is None: return (None, None) scheme = self.versioning_class() #去配置中版本类,实例化 return (scheme.determine_version(request, *args, **kwargs), scheme) #返回这个实例的determine_version()方法的调用结果 ,和这个实例
这个determine_version() 方法只有两种返回结果,一个是返回版本信息,一个报异常。
4.2 全局配置与局部配置
全局配置
关于版本的认证,彻底不可用rest_framework提供的版本认证的类进行一个全局配置 ,能够经过from rest_framework.versioning,获取
def determine_version(self, request, *args, **kwargs): version = kwargs.get(self.version_param, self.default_version) if version is None: version = self.default_version 一、这个是获取版本的源码,能够看到他是从URL中获取一个参数,这个参数,设置的是version_param ,因此,这个地方设置的是什么参数,URL上就要默认的别名要与这个参数一致,,例如: url('api/(?P<version>v1+)/order$' ,views.OrderView.as_view() ,name='uuu') REST_FRAMEWORK ={ 'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning' , 'VERSION_PARAM':'version', 'ALLOWED_VERSIONS':['v1' ,'v2'] } 二、咱们看到还有一个ALLOWED_VERSIONS这个参数,这个参数是默认当前有多少个个版本号,加入说咱们只有两个版本,可是URL中去是一个v100,不在这个范围内,也会报错。
五、解析器
5.一、 做用,用来解析发送的post请求中的请求体的数据,当post请求头中ContentType不在是x-www-form-urlencode 和请求体的数据格式是 name=eric&age=26 时, 经过request.POST是拿不到请求体中的数据的。
同时,咱们的ContentType,能够决定,发送post请求时,post请求体中的数格格式。而在MVC这种先后端分离的结构中,数据都是经过json进行传输的。
因此,请求头中的ContentType 就会变成application/json 格式,这个时候请求体中的数据格式也发生变化,能够是{"name":"eric","age":18},这里面有一个细节 就是必定是双引号,否则restframework,内部的loads反序列化不了会报错。
二、解析器源码剖析流程
六、序列化(serialize)
序列化主要有两方面功能,第一是序列化,第二个就是数据验证,其实序列化,和django自己的form和ModelForm很是类似
6.1 序列化源码流程
6.2验证源码流程
七、分页(pagination)
八、视图(view)
九、路由
十、渲染器