rest framework框架
- 我们来看一段伪代码,MyClassView继承了APIView就有了APIView的功能
class APIView(View):
pass
class MyClassView(APIView):
pass
- 基于Django的CBV
from django.views import View
from django.http import HttpResponse
class MyClassView(View):
def get(self, request, *args, **kwargs):
ret = {
"state_code": 1000,
"msg": "successful"
}
import json
return HttpResponse(json.dumps(ret), status=201)
def post(self, request, *args, **kwargs):
return HttpResponse("created successful")
def delete(self, request, *args, **kwargs):
return HttpResponse("delete successful")
- 基于DRF的CBV ,DRF的APIView在Django的View基础上,增加和丰富了一些功能
from django.views import View
from django.http import HttpResponse
from rest_framework.views import APIView
class MyClassView(APIView):
def get(self, request, *args, **kwargs):
ret = {
"state_code": 1000,
"msg": "successful"
}
import json
return HttpResponse(json.dumps(ret), status=201)
def post(self, request, *args, **kwargs):
return HttpResponse("created successful")
def delete(self, request, *args, **kwargs):
return HttpResponse("delete successful")
原理(流程)
- 当请求进来,先找CBV里面的dispatch方法
"""
rest_framework\views.py
"""
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进行加工(丰富了一些功能)
request = self.initialize_request(request, *args, **kwargs)
# 获取原生request,request._request
# 获取认证类的对象,request.authenticators
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
- 反射
- request加强
- self.initialize_request方法做了什么?
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request)
# 加工后新生成了Request对象
return Request(
request, # 原本的那个request
parsers=self.get_parsers(),
authenticators=self.get_authenticators(), # 认证相关
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
- self.get_authenticators()方法
def get_authenticators(self):
"""
Instantiates and returns the list of authenticators that this view can use.
"""
# self.authentication_classes = [Dog,Cat] auth()就是Dog和Cat对象,被装进列表里面
return [auth() for auth in self.authentication_classes]
- get_authenticators()方法中的self.authentication_classes,先从当前类找,有就使用当前类的authentication_classes,没有就使用父类的authentication_classes,在这里使用的是APIView里面的
- 回到dispatch方法,我们可以看到其实request对象里面就有原生request和[BasicAuthentication,]
- 拿到原生request方法
- 获取认证类的对象,request.authenticators和原生request
- 我们可以查看dispatch方法里面的反射前做了是什么,self.initial方法
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)
- 父类的perform_authentication()方法
- 找到user
# _authenticate源码
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()
登陆认证
- 我们可以编写一个自己的认证类
class MyAuthentication(object):
def authenticate(self, request):
token = request._request.GET.get('token')
if not token:
from rest_framework import exceptions
raise exceptions.AuthenticationFailed("对不起,用户认证失败")
return ("zhangsan", None)
- postman验证
- 解决报错
- postman验证
- 解决方案2
- 以后我们比如有些API需要认证才能看,我们就可以在这里进行操作
DRF认证流程:
- 请求进来先走dispatch方法
- dispatch方法里面封装了request
- 调用initial
-
调用perform_authentication()
取user方法
- user方法里面调用了认证对象
- 遍历认证