安装
pip3 install djangorestframework
使用
基于cbv使用rest_framework框架from rest_framework.views import APIView # rest_framework框架,继承View class ApiTest(APIView): pass当用户请求进来,执行父类的as_view方法, 返回view函数,执行dispatch方法,由于继承了APIView,会执行此类下边的dispatch方法
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 这里用initalize_request方法对原生的request进行加工
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
# 对加工之后的request处理,看下这里边的逻辑
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)
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
可以看到,APIView类下的dispatch方法相比于View中的dispatch方法,除了反射请求还多了一些操作
比如,对本来的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属性,还有一些其他的属性,
这里看下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.authentication_classes点开之后是读取的rest_frame的配置文件
class APIView(View):
# The following policies may be set at either globally, or per-view.
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES #这里
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
metadata_class = api_settings.DEFAULT_METADATA_CLASS
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
如果我们在我们自己的类里边写入authentication_classes参数,就可以读取我们自己设置的,不用APIView下边的
from rest_framework.authentication import BasicAuthentication
class ApiTest(APIView):
authentication_classes = [BasicAuthentication]
到这里,我们已经大概知道dispatch对request进行了一些封装,接下来看下边的代码
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 这里用initalize_request方法对原生的request进行加工
request = self.initialize_request(request, *args, **kwargs)
self.request = request # 赋值
self.headers = self.default_response_headers # deprecate? -------------------------------------------------------------------------------------------
try:
# 对加工之后的request处理,看下这里边的逻辑
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)
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
try下边的initial方法,把封装了数据之后的request当参数,我们点开这个方法
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)
......
self.perform_authentication(request) # 封装过数据之后的request,认证用
self.check_permissions(request)
self.check_throttles(request)
发现有一个perform_authentication方法,点开这个方法里边执行了user属性方法
@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
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()
修改authentacate方法,实现验证功能
from django.shortcuts import HttpResponse
import json
from rest_framework.views import APIView # rest_framework框架,继承View
from rest_framework.authentication import BasicAuthentication
from rest_framework import exceptions # 验证失败触发异常
class Myauthentication(object):
def authenticate(self, request):
username = request._request.GET.get("username") # 验证成功返回元组
if not username:
raise exceptions.AuthenticationFailed("用户名未登录") # 无返回验证失败,触发异常
return ("status",1)
def authenticate_header(self, val):
pass
class ApiTest(APIView):
authentication_classes = [Myauthentication] # 通过自定义的类做认证
def get(self, request, *args, **kwargs): # 用于处理get请求
print(request)
res = {
"code": 1000,
"msg": "hello world"
}
return HttpResponse(json.dumps(res))
def post(self, request, *args, **kwargs):
return HttpResponse("post")
def put(self, request, *args, **kwargs):
return HttpResponse("put")
def delete(self, request, *args, **kwargs):
return HttpResponse("delete")
查看更多关于rest_framework认证流程的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did171885