标签:art ide 其他 django 代码 更新 data format 封装
(一)、创建视图函数
Note
创建视图函数后,前端发起请求,url分配路由,执行视图类,视图类中执行对应方法必须经过dispatch()即调度方法
from rest_framework.views import APIView
from django.shortcuts import HttpResponse
import json
class DogView(APIView):
def get(self, request, *args, **kwargs):
result = {
‘code‘: ‘10000‘,
‘msg‘: ‘数据创建成功‘
}
return HttpResponse(json.dumps(result))
def post(self, request, *args, **kwargs):
return HttpResponse('创建一条订单')
def put(self, request, *args, **kwargs):
return HttpResponse('更新一条订单')
def delete(self, request, *args, **kwargs):
return HttpResponse('删除一条订单')
(二)、运行dispatch方法
Note
如果自己定义了dispatch方法,则程序运行自定义方法,如果没有,程序运行源码中的dispatch方法。从dispatch方法中可以找到原生request在作为参数传递后被initialize_request()函数进行了加工,通过加工的request获得的值包括原生的request和BaseAuthentication实例化对象,所以我们需要找到initialize_request()。
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)
‘‘‘
对原生的request进行加工,获得到的request已经不是原来的request,还包括了其他的参数,
可以通过新的request获取到内部包含的参数
加工后的request : Restquest(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
))
'''
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
self.initial(request, *args, **kwargs)
# 把加工后的request当作参数传递给了initial()函数
# 需要把在这里查找initial()函数
# 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
查看initialize_request()函数
Note
在initialize_request()函数中返回了authenticators, 通过观察可以看出,authenticators的值来自于另外一个函数get_authenticators()。
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(),
# authenticators获取到的是实例化后的类对象列表,即[Foo(), Bar()]
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
找到函数self.get_authenticators()
Note
这个函数中实质上是把一个认证类列表实例化为对象列表进行返回,这里就可以得出在上一个驶入函数中的authenticators是一个实例化对象列表。需要继续往源头找,查找authentication_classes
def get_authenticators(self):
"""
Instantiates and returns the list of authenticators that this view can use.
"""
# 例如self.authentication_classes = [foo, bar]
return [auth() for auth in self.authentication_classes]
# 列表生成式,auth获取到的是列表中的类,auth()是把获取到的类对象进行实例化操作
查找authentication_classes类
Note
在自己编写的代码中并没有定义authentication_classes类,所以程序会从继承的类中去查找,视图类继承自APIView,所以在APIView中找到类authentication_classes。
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
# 继承自APIView中的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
Summary
从上述的逻辑可以看出最终要执行的是AUTHENTICATION_CLASSES,所有的程序中都是如果有自定义程序会覆盖掉框架封装好的,没有自定义,程序才会执行封装好的代码。AUTHENTICATION_CLASSES类是这个逻辑中最重要的一环。
上边的逻辑查找到了最基本的Authentication_classes,并且得到加工后的request包含两部分内容:原生的request、Authentication_classes实例化后得到的对象列表,此时需要继续执行dispatch(),执行到try语句时,加工后的request作为参数传递给initial()函数,并执行该函数,此时需要到request.py中查找initial()函数。
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类中查找到request被传递进行,原生的参数在调用的时候格式为:request._request, 加工后的直接是request.属性
class Request:
"""
Wrapper allowing to enhance a standard HttpRequest
instance.
Kwargs:
- request(HttpRequest). The original request instance.
- parsers_classes(list/tuple). The parsers to use for parsing the
request content.
- authentication_classes(list/tuple). The authentications used to try
authenticating the request's user.
"""
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
assert isinstance(request, HttpRequest), (
'The `request` argument must be an instance of '
'`django.http.HttpRequest`, not `{}.{}`.'
.format(request.__class__.__module__, request.__class__.__name__)
)
self._request = request
# 加工后的request被作为参数传递,那么传递后相对于本类即为原生的request。
self.parsers = parsers or ()
self.authenticators = authenticators or ()
self.negotiator = negotiator or self._default_negotiator()
self.parser_context = parser_context
self._data = Empty
self._files = Empty
self._full_data = Empty
self._content_type = Empty
self._stream = Empty
如果进行认证,必须通过user,此时需要查找user程序是否存在,在Request类中找到了user函数,user()方法执行了_authenticate(),查找_authenticate()
@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()
# 执行_authenticate()
return self._user
查找_authenticate(),在_authenticate()方法中查找到Authenticator_classes生成的实例化列表类对象,循环的对象具有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:
raise self._not_authenticated()
if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
return self._not_authenticated()
通过上述逻辑的整体分析,我们可以编写一个自定义的认证类供视图函数来调用
from rest_framework import exceptions
# 创建自定义的认证类
class MyAuthentication(object):
def authenticate(self, request):
token = request._request.GET.get('token')
# 当前传递的参数request是加工过的,需要通过原生的request(获取方法: _request)获取token信息
if not token:
# 如果不存在抛出异常
raise exceptions.AuthenticationFailed("认证失败")
# 存在返回元组
return ('alax', None)
def authenticate(self, val):
pass
class DogView(APIView):
'''
需要认证的视图类直接通过authentication_classes=[类名,]的方式来使用
'''
authentication_classes = [MyAuthentication]
def get(self, reqeust, *args, **kwargs):
result = {
'code': '10000',
'msg': '获取到所有的数据'
}
return HttpResponse(json.dumps(result))
def post(self, request, *args, **kwargs):
return HttpResponse("创建Dog")
def put(self, request, *args, **kwargs):
return HttpResponse("更新Dog")
def delete(self, request, *args, **kwargs):
return HttpResponse("删除Dog")
标签:art ide 其他 django 代码 更新 data format 封装
原文地址:https://www.cnblogs.com/ddzc/p/12121140.html