rest-framework组件源剖析码
class Request(object)
def _hasattr(obj, name):
return not getattr(obj, name) is Empty
class Request(object):
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
self._full_data = Empty # 一个类名
@property
def query_params(self):
"""
url上的参数
"""
return self._request.GET
@property
def data(self):
'''
非get请求的数据
'''
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
return self._full_data
def _load_data_and_files(self):
"""
Parses the request content into `self.data`.
"""
if not _hasattr(self, '_data'):
self._data, self._files = self._parse()
if self._files:
self._full_data = self._data.copy()
self._full_data.update(self._files)
else:
self._full_data = self._data
# if a form media type, copy data & files refs to the underlying
# http request so that closable objects are handled appropriately.
if is_form_media_type(self.content_type):
self._request._post = self.POST
self._request._files = self.FILES
class APIView(View)
class APIView(View):
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 返回新的request对象
request = self.initialize_request(request, *args, **kwargs)
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
# 初始化方法
def initial(self, request, *args, **kwargs):
self.format_kwarg = self.get_format_suffix(**kwargs)
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
# 认证组件
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 get_permissions(self):
return [permission() for permission in self.permission_classes]
# 频率
def check_throttles(self, request):
for throttle in self.get_throttles():
if not throttle.allow_request(request, self):
self.throttled(request, throttle.wait())
# 获取频率类的列表
def get_throttles(self):
return [throttle() for throttle in self.throttle_classes]
认证组件
class APIView(View):
# 返回新的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
)
class Request:
@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):
"""
self.authenticators = APIView或其子类中authentication_classes中类的实例的列表
"""
for authenticator in self.authenticators:
try:
# 执行实例的authenticate(自定义的校验)方法,传入request
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()
def _not_authenticated(self):
"""
为user和auth赋默认值
"""
self._authenticator = None
if api_settings.UNAUTHENTICATED_USER:
self.user = api_settings.UNAUTHENTICATED_USER()
else:
self.user = None
if api_settings.UNAUTHENTICATED_TOKEN:
self.auth = api_settings.UNAUTHENTICATED_TOKEN()
else:
self.auth = None
在自己没定义校验的情况下APIView中也提供了authentication_classes
from rest_framework.settings import api_settings
class APIView(View):
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
# api_settings是APISettings类的唯一实例
class APISettings(object):
def __init__(self, user_settings=None, defaults=None, import_strings=None):
if user_settings:
self._user_settings = self.__check_user_settings(user_settings)
self.defaults = defaults or DEFAULTS
self.import_strings = import_strings or IMPORT_STRINGS
self._cached_attrs = set()
@property
def user_settings(self):
if not hasattr(self, '_user_settings'):
# 从全局的settings中获得REST_FRAMEWORK字典,这使得我们可以自定义全局验证
self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
return self._user_settings
def __getattr__(self, attr):
# 获取DEFAULT_AUTHENTICATION_CLASSES属性
if attr not in self.defaults:
raise AttributeError("Invalid API setting: '%s'" % attr)
try:
# 从REST_FRAMEWORK字典中取键值
val = self.user_settings[attr]
except KeyError:
# 取不到就去defaults中取
val = self.defaults[attr]
# 下面是通过反射获取类
if attr in self.import_strings:
val = perform_import(val, attr)
# Cache the result
self._cached_attrs.add(attr)
setattr(self, attr, val)
return val
def __check_user_settings(self, user_settings):
SETTINGS_DOC = "http://www.django-rest-framework.org/api-guide/settings/"
for setting in REMOVED_SETTINGS:
if setting in user_settings:
raise RuntimeError("The '%s' setting has been removed. Please refer to '%s' for available settings." % (setting, SETTINGS_DOC))
return user_settings
def reload(self):
for attr in self._cached_attrs:
delattr(self, attr)
self._cached_attrs.clear()
if hasattr(self, '_user_settings'):
delattr(self, '_user_settings')
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)

浙公网安备 33010602011771号