drf(请求封装/认证/权限/节流)
1.请求的封装
class HttpRequest(object):
def __init__(self):
pass @propery
def GET(self):
pass @propery
def POST(self):
pass @propery
def body(self):
pass
class Request(object):
def __init__(self,request):
self._request = request def data(self):
if content-type == "application/json"
reutrn json.loads(self._request.body.decode('urf-8'))
elif content-type == "x-www-...":
return self._request.POST def query_params(self):
return self._reqeust.GET
req = HttpRequest()
request = Request(req)
request.data
request.query_prams
request._request.GET
request._request.POST
request._request.body
drf入口请求流程:
路由
urlpatterns = [
url(r'^order/$', views.OrderView.as_view()),
]视图关系
class View(object):
@classonlymethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
return self.dispatch(request, *args, **kwargs)
return view class APIView(View): @classmethod
def as_view(cls, **initkwargs):
view = super().as_view(**initkwargs)
return csrf_exempt(view)
def dispatch(self, request, *args, **kwargs):
# 新request内部包含老request(_reuqest=老request)
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.initial(request, *args, **kwargs)
# 通过反射执行“get”方法,并传入新的request
handler = getattr(self, request.method.lower())
response = handler(request, *args, **kwargs) # get(requst)
return self.response
class OrderView(APIView): def get(self,request,*args,**kwargs):
return Response('海狗')
2.版本
from django.conf.urls import url,include
from django.contrib import admin
from . import views
urlpatterns = [
url(r'^order/$', views.OrderView.as_view()),
]
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
class OrderView(APIView):
def get(self,request,*args,**kwargs):
print(request.version)
print(request.versioning_scheme)
return Response('...')
def post(self,request,*args,**kwargs):
return Response('post')
源码流程:
class APIView(View):
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
def dispatch(self, request, *args, **kwargs):
# ###################### 第一步 ###########################
"""
request,是django的request,它的内部有:request.GET/request.POST/request.method
args,kwargs是在路由中匹配到的参数,如:
url(r'^order/(\d+)/(?P<version>\w+)/$', views.OrderView.as_view()),
http://www.xxx.com/order/1/v2/
"""
self.args = args
self.kwargs = kwargs
"""
request = 生成了一个新的request对象,此对象的内部封装了一些值。
request = Request(request)
- 内部封装了 _request = 老的request
"""
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
# ###################### 第二步 ###########################
self.initial(request, *args, **kwargs)
执行视图函数。。 def initial(self, request, *args, **kwargs):
# ############### 2.1 处理drf的版本 ##############
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
...
def determine_version(self, request, *args, **kwargs):
if self.versioning_class is None:
return (None, None)
scheme = self.versioning_class() # obj = XXXXXXXXXXXX()
return (scheme.determine_version(request, *args, **kwargs), scheme)
class OrderView(APIView):
versioning_class = URLPathVersioning
def get(self,request,*args,**kwargs):
print(request.version)
print(request.versioning_scheme)
return Response('...')
def post(self,request,*args,**kwargs):
return Response('post')
class URLPathVersioning(BaseVersioning):
"""
urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),
]
"""
invalid_version_message = _('Invalid version in URL path.')
def determine_version(self, request, *args, **kwargs):
version = kwargs.get(self.version_param, self.default_version)
if version is None:
version = self.default_version
if not self.is_allowed_version(version):
raise exceptions.NotFound(self.invalid_version_message)
return version
使用(局部)
url中写version
url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),
在视图中应用
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.versioning import URLPathVersioning
class OrderView(APIView):
versioning_class = URLPathVersioning
def get(self,request,*args,**kwargs):
print(request.version)
print(request.versioning_scheme)
return Response('...')
def post(self,request,*args,**kwargs):
return Response('post')在settings中配置
REST_FRAMEWORK = {
"PAGE_SIZE":2,
"DEFAULT_PAGINATION_CLASS":"rest_framework.pagination.PageNumberPagination",
"ALLOWED_VERSIONS":['v1','v2'],
'VERSION_PARAM':'version'
}
使用(全局)推荐
url中写version
url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),
url(r'^(?P<version>\w+)/users/$', users_list, name='users-list'),在视图中应用
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.versioning import URLPathVersioning
class OrderView(APIView):
def get(self,request,*args,**kwargs):
print(request.version)
print(request.versioning_scheme)
return Response('...')
def post(self,request,*args,**kwargs):
return Response('post')在settings中配置
REST_FRAMEWORK = {
"PAGE_SIZE":2,
"DEFAULT_PAGINATION_CLASS":"rest_framework.pagination.PageNumberPagination",
"DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
"ALLOWED_VERSIONS":['v1','v2'],
'VERSION_PARAM':'version'
}
####
3.认证(面试)
from django.conf.urls import url,include
from django.contrib import admin
from . import views
urlpatterns = [
url(r'^login/$', views.LoginView.as_view()),
url(r'^order/$', views.OrderView.as_view()),
url(r'^user/$', views.UserView.as_view()),
]
import uuid
from django.shortcuts import render
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from rest_framework.versioning import URLPathVersioning
from rest_framework.views import APIView
from rest_framework.response import Response
from . import models
class LoginView(APIView):
def post(self,request,*args,**kwargs):
user_object = models.UserInfo.objects.filter(**request.data).first()
if not user_object:
return Response('登录失败')
random_string = str(uuid.uuid4())
user_object.token = random_string
user_object.save()
return Response(random_string)
class MyAuthentication:
def authenticate(self, request):
"""
Authenticate the request and return a two-tuple of (user, token).
"""
token = request.query_params.get('token')
user_object = models.UserInfo.objects.filter(token=token).first()
if user_object:
return (user_object,token)
return (None,None)
class OrderView(APIView):
authentication_classes = [MyAuthentication, ]
def get(self,request,*args,**kwargs):
print(request.user)
print(request.auth)
return Response('order')
class UserView(APIView):
authentication_classes = [MyAuthentication,]
def get(self,request,*args,**kwargs):
print(request.user)
print(request.auth)
return Response('user')
源码分析
class Request:
def __init__(self, request,authenticators=None):
self._request = request
self.authenticators = authenticators or ()
@property
def user(self):
"""
Returns the user associated with the current request, as authenticated
by the authentication classes provided to the request.
"""
if not hasattr(self, '_user'):
with wrap_attributeerrors():
self._authenticate()
return self._user
def _authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
for authenticator in self.authenticators:
try:
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
self._not_authenticated()
raise
if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
return
self._not_authenticated()
@user.setter
def user(self, value):
"""
Sets the user on the current request. This is necessary to maintain
compatibility with django.contrib.auth where the user property is
set in the login and logout functions.
Note that we also set the user on Django's underlying `HttpRequest`
instance, ensuring that it is available to any middleware in the stack.
"""
self._user = value
self._request.user = value
class APIView(View):
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
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.
"""
# ###################### 第一步 ###########################
"""
request,是django的request,它的内部有:request.GET/request.POST/request.method
args,kwargs是在路由中匹配到的参数,如:
url(r'^order/(\d+)/(?P<version>\w+)/$', views.OrderView.as_view()),
http://www.xxx.com/order/1/v2/
"""
self.args = args
self.kwargs = kwargs
"""
request = 生成了一个新的request对象,此对象的内部封装了一些值。
request = Request(request)
- 内部封装了 _request = 老的request
- 内部封装了 authenticators = [MyAuthentication(), ]
"""
request = self.initialize_request(request, *args, **kwargs)
self.request = 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(), # [MyAuthentication(),]
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
def get_authenticators(self):
"""
Instantiates and returns the list of authenticators that this view can use.
"""
return [ auth() for auth in self.authentication_classes ]
class LoginView(APIView):
authentication_classes = []
def post(self,request,*args,**kwargs):
user_object = models.UserInfo.objects.filter(**request.data).first()
if not user_object:
return Response('登录失败')
random_string = str(uuid.uuid4())
user_object.token = random_string
user_object.save()
return Response(random_string)
class OrderView(APIView):
# authentication_classes = [TokenAuthentication, ]
def get(self,request,*args,**kwargs):
print(request.user)
print(request.auth)
if request.user:
return Response('order')
return Response('滚')
class UserView(APIView):
同上
总结
当用户发来请求时,找到认证的所有类并实例化成为对象列表,然后将对象列表封装到新的request对象中。
以后在视同中调用request.user
在内部会循环认证的对象列表,并执行每个对象的authenticate方法,该方法用于认证,他会返回两个值分别会赋值给
request.user/request.auth
作业:将认证的功能添加到呼啦圈中。
登录表
登录视图
写认证类
应用认证类:全局应用
Login视图不应用认证
4.权限
from rest_framework.permissions import BasePermission
from rest_framework import exceptions
class MyPermission(BasePermission):
message = {'code': 10001, 'error': '你没权限'}
def has_permission(self, request, view):
"""
Return `True` if permission is granted, `False` otherwise.
"""
if request.user:
return True
# raise exceptions.PermissionDenied({'code': 10001, 'error': '你没权限'})
return False
def has_object_permission(self, request, view, obj):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return False
class OrderView(APIView):
permission_classes = [MyPermission,]
def get(self,request,*args,**kwargs):
return Response('order')
class UserView(APIView):
permission_classes = [MyPermission, ]
def get(self,request,*args,**kwargs):
return Response('user')
REST_FRAMEWORK = {
"PAGE_SIZE":2,
"DEFAULT_PAGINATION_CLASS":"rest_framework.pagination.PageNumberPagination",
"DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
"ALLOWED_VERSIONS":['v1','v2'],
'VERSION_PARAM':'version',
"DEFAULT_AUTHENTICATION_CLASSES":["kka.auth.TokenAuthentication",]
}
源码分析
class APIView(View):
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
def dispatch(self, request, *args, **kwargs):
封装request对象
self.initial(request, *args, **kwargs)
通过反射执行视图中的方法
def initial(self, request, *args, **kwargs):
版本的处理
# 认证
self.perform_authentication(request) # 权限判断
self.check_permissions(request)
self.check_throttles(request)
def perform_authentication(self, request):
request.user def check_permissions(self, request):
# [对象,对象,]
for permission in self.get_permissions():
if not permission.has_permission(request, self):
self.permission_denied(request, message=getattr(permission, 'message', None))
def permission_denied(self, request, message=None):
if request.authenticators and not request.successful_authenticator:
raise exceptions.NotAuthenticated()
raise exceptions.PermissionDenied(detail=message)
def get_permissions(self):
return [permission() for permission in self.permission_classes]
class UserView(APIView):
permission_classes = [MyPermission, ]
def get(self,request,*args,**kwargs):
return Response('user')
实现呼啦圈
视图:ListAPIView
序列化:多个序列化
分页:给列表页面做分页
版本:版本设置
认证:认证流程 request.user赋值
权限:能否访问
drf(请求封装/认证/权限/节流)的更多相关文章
- drf:restful概念,类继承关系,drf请求封装,drf请求流程,版本控制组件,认证组件(token),权限组件
1.restful规范 resfful规范的概念最重要: 是一套规范,规则,用于程序之间进行数据交换的约定. 他规定了一些协议,对我们感受最直接的就是,以前写增删改查的时候需要些四个视图寒素,rest ...
- (四) DRF认证, 权限, 节流
一.Token 认证的来龙去脉 摘要 Token 是在服务端产生的.如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端.前端可以在每次请求的时候带上 To ...
- day74:drf:drf其他功能:认证/权限/限流/过滤/排序/分页/异常处理&自动生成接口文档
目录 1.django-admin 2.认证:Authentication 3.权限:Permissions 4.限流:Throttling 5.过滤:Filtering 6.排序:OrderingF ...
- 8) drf 三大认证 认证 权限 频率
一.三大认证功能分析 1)APIView的 dispath(self, request, *args, **kwargs) 2)dispath方法内 self.initial(request, *ar ...
- DRF 版本、认证、权限、限制、解析器和渲染器
目录 一.DRF之版本控制 为什么要有版本控制? DRF提供的版本控制方案 版本的使用 全局配置 局部配置(使用较少) 二.DRF之认证 内置的认证 步骤 三.DRF之权限 1.自定义一个权限类 2. ...
- drf框架中认证与权限工作原理及设置
0909自我总结 drf框架中认证与权限工作原理及设置 一.概述 1.认证 工作原理 返回None => 游客 返回user,auth => 登录用户 抛出异常 => 非法用户 前台 ...
- 实战-DRF快速写接口(认证权限频率)
实战-DRF快速写接口 开发环境 Python3.6 Pycharm专业版2021.2.3 Sqlite3 Django 2.2 djangorestframework3.13 测试工具 Postma ...
- 【DRF框架】认证组件
DRF框架的认证组件 核心代码: self.perform_authentication(request) 框架自带模块: from rest_framework import a ...
- 07 drf源码剖析之节流
07 drf源码剖析之节流 目录 07 drf源码剖析之节流 1. 节流简述 2. 节流使用 3. 源码剖析 总结: 1. 节流简述 节流类似于权限,它确定是否应授权请求.节流指示临时状态,并用于控制 ...
随机推荐
- 一致性 hash 算法( consistent hashing )及java实现
consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在cache 系统中应用越来越广泛: 1 基 ...
- 吴裕雄--天生自然操作系统操作笔记:window10显示隐藏文件夹
基于安全考虑,操作系统会隐藏一些文件和文件夹,防止误删除操作.但有可能是个别人为了隐藏一些私密数据,也同样采取隐藏的方式.
- VS自身的单元测试方法DEMO
///用来修饰测试类 [TestClass()] public class Program { private TestContext testContextInstance; /// <sum ...
- NBA球星的生意经 个人流量化之路
个人流量化之路" title="NBA球星的生意经 个人流量化之路"> 在国人欢天喜地的庆祝新春佳节之时,大洋彼岸也在进行着让全球篮球迷为之"着魔&quo ...
- python——实现三级菜单选择的功能(原创)
#coding:utf-8 dict={'beijing':{'haidingqu':['qinghe','keji'],'chaoyangqu':['q','w']},'shandong':{'li ...
- 腾讯入股Snap,能救“阅后即焚”的命吗?
互联网社交的强大包容性,让各种社交形式都能有着较多的受众群体.普适性极广的QQ.微信."脸谱":专攻陌生人社交的陌陌:让人们发布意见的微博--当然也少不了"阅 ...
- 手机视频APP将关闭 生态梦成空的三星如何自救?
生态梦成空的三星如何自救?"> 三星如今的处境,只能用"屋漏偏逢连夜雨"来形容.继营收.利润.智能手机销量等大幅下滑之后,裁员也接踵而来,股价的下跌也自然在情理之中 ...
- Rong's Portfolio
車架貼標設計 Velocite SYN frame decals 以簡潔設計的原則,分別依公路車.登山車.電動車的屬性設計表面塗裝曲線,針對車架特殊造型設計貼標突顯其功能,並搭配品牌基本色與市場偏好色 ...
- Android注解支持Support Annotations详解
###注解支持(Support Annotations)Android support library从19.1版本开始引入了一个新的注解库,它包含很多有用的元注解,你能用它们修饰你的代码,帮助你发现 ...
- SAT考试里最难的数学题? · 三只猫的温暖
问题 今天无意中在Quora上看到有人贴出来一道号称是SAT里最难的一道数学题,一下子勾起了我的兴趣.于是拿起笔来写写画画,花了差不多十五分钟搞定.觉得有点意思,决定把解题过程记下来.原帖的图太小,我 ...