Django REST framework 源码解析

先放图,放图说话,可能有点长

主流程 这个颜色

从setting导入默认数据流程是 这个颜色

主流程大概流程写一下:as_view 实际返回view,并把参数{"get":"list","post":"create"}传递给view,view会根据传入的参数设置成 handle=list,get=handle 然后执行dispatch函数,dispatch 先 执行initialize_request(重新封装request,并调用解析器) 然后执行initial函数(调用版本,认证,频率,权限组件),通过之后,调用 finalize_response (渲染器,分页),最后返回结果

 

发现一片不错的博文,可以参考https://www.jianshu.com/p/a7fc2f4925d6

# 来个url
url(r'^books/$', views.BookViewSet.as_view({"get":"list","post":"create"}),name="book_list"
######################## viewsets.py ############################
class ViewSetMixin(object):@classonlymethoddef as_view(cls, actions=None, **initkwargs):      # 1、as_view函数,返回viewcls.name = Nonecls.description = Nonecls.suffix = Nonecls.detail = Nonecls.basename = Noneif not actions:raise TypeError("The `actions` argument must be provided when ""calling `.as_view()` on a ViewSet. For example ""`.as_view({'get': 'list'})`")# sanitize keyword argumentsfor key in initkwargs:if key in cls.http_method_names:raise TypeError("You tried to pass in the %s method name as a ""keyword argument to %s(). Don't do that."% (key, cls.__name__))if not hasattr(cls, key):raise TypeError("%s() received an invalid keyword %r" % (cls.__name__, key))# name and suffix are mutually exclusiveif 'name' in initkwargs and 'suffix' in initkwargs:raise TypeError("%s() received both `name` and `suffix`, which are ""mutually exclusive arguments." % (cls.__name__))def view(request, *args, **kwargs):           # 2、执行viewself = cls(**initkwargs)self.action_map = actions    # 刚才传入的{"get":"list","post":"create"}for method, action in actions.items():    # 3、设置成 list() = get()handler = getattr(self, action)   # 获取 list 函数setattr(self, method, handler)    # 为 get 设置 listif hasattr(self, 'get') and not hasattr(self, 'head'):self.head = self.getself.request = request  # 设置requestself.args = args        # 保存参数self.kwargs = kwargs# And continue as usualreturn self.dispatch(request, *args, **kwargs)   # 4、dispatchupdate_wrapper(view, cls, updated=())update_wrapper(view, cls.dispatch, assigned=())view.cls = clsview.initkwargs = initkwargsview.actions = actions         # {"get":"list","post":"create"} 保存下来,传入到actionsreturn csrf_exempt(view)       # 返回viewdef initialize_request(self, request, *args, **kwargs):    # 6、为requset重新封装request = super(ViewSetMixin, self).initialize_request(request, *args, **kwargs) # 调用父类的initialize_requestmethod = request.method.lower()if method == 'options':self.action = 'metadata'else:self.action = self.action_map.get(method)    # 传入的{"get":"list","post":"create"}return requestdef reverse_action(self, url_name, *args, **kwargs):url_name = '%s-%s' % (self.basename, url_name)kwargs.setdefault('request', self.request)return reverse(url_name, *args, **kwargs)@classmethoddef get_extra_actions(cls):return [method for _, method in getmembers(cls, _is_extra_action)]def get_extra_action_url_map(self):action_urls = OrderedDict()# exit early if `detail` has not been providedif self.detail is None:return action_urls# filter for the relevant extra actionsactions = [action for action in self.get_extra_actions()if action.detail == self.detail]for action in actions:try:url_name = '%s-%s' % (self.basename, action.url_name)url = reverse(url_name, self.args, self.kwargs, request=self.request)view = self.__class__(**action.kwargs)action_urls[view.get_view_name()] = urlexcept NoReverseMatch:pass  # URL requires additional arguments, ignorereturn action_urls

流程2:在setting中找到相应的配置文件

(1)实例化api_settings

api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) # DEFAULTS为默认配置 IMPORT_STRINGS相应模块

ViewSetMixin 中没有dispatch ,找父类的,在APIView中找到了

######################## view.py ############################
class APIView(View):# The following policies may be set at either globally, or per-view.renderer_classes = api_settings.DEFAULT_RENDERER_CLASSESparser_classes = api_settings.DEFAULT_PARSER_CLASSESauthentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSESthrottle_classes = api_settings.DEFAULT_THROTTLE_CLASSESpermission_classes = api_settings.DEFAULT_PERMISSION_CLASSEScontent_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASSmetadata_class = api_settings.DEFAULT_METADATA_CLASSversioning_class = api_settings.DEFAULT_VERSIONING_CLASS   # 版本的配置类# (2)api_settings.* 其实是执行api_settings的__get__ 方法 ,返回相应的类# Allow dependency injection of other settings to make testing easier.settings = api_settingsschema = DefaultSchema()@classmethoddef as_view(cls, **initkwargs):if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):def force_evaluation():raise RuntimeError('Do not evaluate the `.queryset` attribute directly, ''as the result will be cached and reused between requests. ''Use `.all()` or call `.get_queryset()` instead.')cls.queryset._fetch_all = force_evaluationview = super(APIView, cls).as_view(**initkwargs)view.cls = clsview.initkwargs = initkwargs# Note: session based authentication is explicitly CSRF validated,# all other authentication is CSRF exempt.return csrf_exempt(view)   # 返回View类 中的view@propertydef allowed_methods(self):"""Wrap Django's private `_allowed_methods` interface in a public property."""return self._allowed_methods()@propertydef default_response_headers(self):headers = {'Allow': ', '.join(self.allowed_methods),}if len(self.renderer_classes) > 1:headers['Vary'] = 'Accept'return headersdef http_method_not_allowed(self, request, *args, **kwargs):"""If `request.method` does not correspond to a handler method,determine what kind of exception to raise."""raise exceptions.MethodNotAllowed(request.method)def permission_denied(self, request, message=None):"""If request is not permitted, determine what kind of exception to raise."""if request.authenticators and not request.successful_authenticator:raise exceptions.NotAuthenticated()raise exceptions.PermissionDenied(detail=message)def throttled(self, request, wait):"""If request is throttled, determine what kind of exception to raise."""raise exceptions.Throttled(wait)def get_authenticate_header(self, request):"""If a request is unauthenticated, determine the WWW-Authenticateheader to use for 401 responses, if any."""authenticators = self.get_authenticators()if authenticators:return authenticators[0].authenticate_header(request)def get_parser_context(self, http_request):"""Returns a dict that is passed through to Parser.parse(),as the `parser_context` keyword argument."""# Note: Additionally `request` and `encoding` will also be added#       to the context by the Request object.return {'view': self,'args': getattr(self, 'args', ()),'kwargs': getattr(self, 'kwargs', {})}def get_renderer_context(self):"""Returns a dict that is passed through to Renderer.render(),as the `renderer_context` keyword argument."""# Note: Additionally 'response' will also be added to the context,#       by the Response object.return {'view': self,'args': getattr(self, 'args', ()),'kwargs': getattr(self, 'kwargs', {}),'request': getattr(self, 'request', None)}def get_exception_handler_context(self):"""Returns a dict that is passed through to EXCEPTION_HANDLER,as the `context` argument."""return {'view': self,'args': getattr(self, 'args', ()),'kwargs': getattr(self, 'kwargs', {}),'request': getattr(self, 'request', None)}def get_view_name(self):"""Return the view name, as used in OPTIONS responses and in thebrowsable API."""func = self.settings.VIEW_NAME_FUNCTIONreturn func(self)def get_view_description(self, html=False):"""Return some descriptive text for the view, as used in OPTIONS responsesand in the browsable API."""func = self.settings.VIEW_DESCRIPTION_FUNCTIONreturn func(self, html)# API policy instantiation methodsdef get_format_suffix(self, **kwargs):"""Determine if the request includes a '.json' style format suffix"""if self.settings.FORMAT_SUFFIX_KWARG:return kwargs.get(self.settings.FORMAT_SUFFIX_KWARG)def get_renderers(self):"""Instantiates and returns the list of renderers that this view can use."""return [renderer() for renderer in self.renderer_classes]def get_parsers(self):"""Instantiates and returns the list of parsers that this view can use."""return [parser() for parser in self.parser_classes]def get_authenticators(self):"""Instantiates and returns the list of authenticators that this view can use."""return [auth() for auth in self.authentication_classes]def get_permissions(self):"""Instantiates and returns the list of permissions that this view requires."""return [permission() for permission in self.permission_classes]def get_throttles(self):"""Instantiates and returns the list of throttles that this view uses."""return [throttle() for throttle in self.throttle_classes]def get_content_negotiator(self):"""Instantiate and return the content negotiation class to use."""if not getattr(self, '_negotiator', None):self._negotiator = self.content_negotiation_class()return self._negotiatordef get_exception_handler(self):"""Returns the exception handler that this view uses."""return self.settings.EXCEPTION_HANDLER# API policy implementation methodsdef perform_content_negotiation(self, request, force=False):"""Determine which renderer and media type to use render the response."""renderers = self.get_renderers()conneg = self.get_content_negotiator()try:return conneg.select_renderer(request, renderers, self.format_kwarg)except Exception:if force:return (renderers[0], renderers[0].media_type)raisedef perform_authentication(self, request):               # 7.2 认证走的函数,实际执行认证类里的 authenticate(self) 方法"""                                                  # 7.2 认证成功返回(认证之后的用户,认证的obj),失败返回(None,None)Perform authentication on the incoming request.Note that if you override this and simply 'pass', then authenticationwill instead be performed lazily, the first time either`request.user` or `request.auth` is accessed."""request.user             # 传入request 的 user 方法def check_permissions(self, request):                   # 7.3 权限走的函数,实际执行类中的has_permission,有权限返回True,无权限返回False"""Check if the request should be permitted.Raises an appropriate exception if the request is not permitted."""for permission in self.get_permissions():if not permission.has_permission(request, self):self.permission_denied(request, message=getattr(permission, 'message', None))def check_object_permissions(self, request, obj):"""Check if the request should be permitted for a given object.Raises an appropriate exception if the request is not permitted."""for permission in self.get_permissions():if not permission.has_object_permission(request, self, obj):self.permission_denied(request, message=getattr(permission, 'message', None))def check_throttles(self, request):                      # 频率走的函数,实际执行类中的allow_request,允许访问返回True,否则返回False"""Check if request should be throttled.Raises an appropriate exception if the request is throttled."""for throttle in self.get_throttles():if not throttle.allow_request(request, self):self.throttled(request, throttle.wait())def determine_version(self, request, *args, **kwargs):    # 7.1 版本走的函数,DRF 提供的版本源码在 相应的博客中"""If versioning is being used, then determine any API version for theincoming request. Returns a two-tuple of (version, versioning_scheme)"""                                  # 7.1.1 self.versioning_class 配置了用自己的,没有配置,用默认的if self.versioning_class is None:    # 7.1.2 版本类为空,返回none,否则调用版本的determine_version方法,返回获取到的版本versionreturn (None, None)              scheme = self.versioning_class()return (scheme.determine_version(request, *args, **kwargs), scheme)  # 7.1.3 返回版本信息和版本类# Dispatch methodsdef initialize_request(self, request, *args, **kwargs):    # 6、为requset重新封装parser_context = self.get_parser_context(request)return Request(request,parsers=self.get_parsers(),                        # 6 解析器再此authenticators=self.get_authenticators(),negotiator=self.get_content_negotiator(),parser_context=parser_context)def initial(self, request, *args, **kwargs):               # 7、版本、频率、认证、权限"""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 requestneg = 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)    # 7.1 获取版本信息,返回值 版本信息,版本类request.version, request.versioning_scheme = version, scheme          # 版本信息,版本类# Ensure that the incoming request is permittedself.perform_authentication(request)                     # 7.2 认证self.check_permissions(request)                          # 7.3 权限self.check_throttles(request)                            # 7.4 频率 def finalize_response(self, request, response, *args, **kwargs):          # 10、返回前的最后一步,"""Returns the final response object."""# Make the error obvious if a proper response is not returnedassert isinstance(response, HttpResponseBase), ('Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` ''to be returned from the view, but received a `%s`'% type(response))if isinstance(response, Response):if not getattr(request, 'accepted_renderer', None):neg = self.perform_content_negotiation(request, force=True)request.accepted_renderer, request.accepted_media_type = negresponse.accepted_renderer = request.accepted_renderer    # 渲染器response.accepted_media_type = request.accepted_media_typeresponse.renderer_context = self.get_renderer_context()# Add new vary headers to the response instead of overwriting.vary_headers = self.headers.pop('Vary', None)if vary_headers is not None:patch_vary_headers(response, cc_delim_re.split(vary_headers))for key, value in self.headers.items():response[key] = valuereturn responsedef handle_exception(self, exc):"""Handle any exception that occurs, by returning an appropriate response,or re-raising the error."""if isinstance(exc, (exceptions.NotAuthenticated,exceptions.AuthenticationFailed)):# WWW-Authenticate header for 401 responses, else coerce to 403auth_header = self.get_authenticate_header(self.request)if auth_header:exc.auth_header = auth_headerelse:exc.status_code = status.HTTP_403_FORBIDDENexception_handler = self.get_exception_handler()context = self.get_exception_handler_context()response = exception_handler(exc, context)if response is None:self.raise_uncaught_exception(exc)response.exception = Truereturn responsedef raise_uncaught_exception(self, exc):if settings.DEBUG:request = self.requestrenderer_format = getattr(request.accepted_renderer, 'format')use_plaintext_traceback = renderer_format not in ('html', 'api', 'admin')request.force_plaintext_errors(use_plaintext_traceback)raise# Note: Views are made CSRF exempt from within `as_view` as to prevent# accidental removal of this exemption in cases where `dispatch` needs to# be overridden.def dispatch(self, request, *args, **kwargs):              # 5、执行dispatchself.args = argsself.kwargs = kwargsrequest = self.initialize_request(request, *args, **kwargs)  # 6、为requset重新封装,其中有解析器self.request = request # 重新赋值self.headers = self.default_response_headers  # deprecate?try:self.initial(request, *args, **kwargs)              # 7、版本、频率、认证、权限# Get the appropriate handler methodif request.method.lower() in self.http_method_names:handler = getattr(self, request.method.lower(),self.http_method_not_allowed) # 8、找个 'get' 函数else:handler = self.http_method_not_allowedresponse = handler(request, *args, **kwargs)        # 9、执行 'get' 函数except Exception as exc:response = self.handle_exception(exc)self.response = self.finalize_response(request, response, *args, **kwargs)  # 10、返回前的最后一步return self.responsedef options(self, request, *args, **kwargs):"""Handler method for HTTP 'OPTIONS' request."""if self.metadata_class is None:return self.http_method_not_allowed(request, *args, **kwargs)data = self.metadata_class().determine_metadata(request, self)return Response(data, status=status.HTTP_200_OK)

附 view 源码

###################### base.py ###############
class View(object):http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']def __init__(self, **kwargs):"""Constructor. Called in the URLconf; can contain helpful extrakeyword arguments, and other things."""# Go through keyword arguments, and either save their values to our# instance, or raise an error.for key, value in six.iteritems(kwargs):setattr(self, key, value)@classonlymethoddef as_view(cls, **initkwargs):"""Main entry point for a request-response process."""for key in initkwargs:if key in cls.http_method_names:raise TypeError("You tried to pass in the %s method name as a ""keyword argument to %s(). Don't do that."% (key, cls.__name__))if not hasattr(cls, key):raise TypeError("%s() received an invalid keyword %r. as_view ""only accepts arguments that are already ""attributes of the class." % (cls.__name__, key))def view(request, *args, **kwargs):self = cls(**initkwargs)if hasattr(self, 'get') and not hasattr(self, 'head'):self.head = self.getself.request = requestself.args = argsself.kwargs = kwargsreturn self.dispatch(request, *args, **kwargs)view.view_class = clsview.view_initkwargs = initkwargs# take name and docstring from classupdate_wrapper(view, cls, updated=())# and possible attributes set by decorators# like csrf_exempt from dispatchupdate_wrapper(view, cls.dispatch, assigned=())return viewdef dispatch(self, request, *args, **kwargs):# Try to dispatch to the right method; if a method doesn't exist,# defer to the error handler. Also defer to the error handler if the# request method isn't on the approved list.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_allowedreturn handler(request, *args, **kwargs)def http_method_not_allowed(self, request, *args, **kwargs):logger.warning('Method Not Allowed (%s): %s', request.method, request.path,extra={'status_code': 405, 'request': request})return http.HttpResponseNotAllowed(self._allowed_methods())def options(self, request, *args, **kwargs):"""Handles responding to requests for the OPTIONS HTTP verb."""response = http.HttpResponse()response['Allow'] = ', '.join(self._allowed_methods())response['Content-Length'] = '0'return responsedef _allowed_methods(self):return [m.upper() for m in self.http_method_names if hasattr(self, m)]

获取配置信息APISettings的源码

############################# setting.py ############################
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             (1)实例化调用的__init__self.import_strings = import_strings or IMPORT_STRINGSself._cached_attrs = set()@propertydef user_settings(self):if not hasattr(self, '_user_settings'):self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})return self._user_settingsdef __getattr__(self, attr):                        # (2)调用getattr方法if attr not in self.defaults:                   # (3)如果名字不在默认中存在,报错raise AttributeError("Invalid API setting: '%s'" % attr)try:                                            # (4)在Django的setting中有就用,没有用默认配置中的配置# Check if present in user settingsval = self.user_settings[attr]except KeyError:# Fall back to defaultsval = self.defaults[attr]# Coerce import strings into classesif attr in self.import_strings:                 # (5)导入相应的模块val = perform_import(val, attr)# Cache the resultself._cached_attrs.add(attr)setattr(self, attr, val)                        # (6)将模块赋值给attr,并返回return valdef __check_user_settings(self, user_settings):SETTINGS_DOC = "https://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_settingsdef reload(self):for attr in self._cached_attrs:delattr(self, attr)self._cached_attrs.clear()if hasattr(self, '_user_settings'):delattr(self, '_user_settings')

下面这个是再导入diango的配置 from django.conf import settings

################################ setting.py ############################################
# 内容有点长,作用是导入Django的settings
def reload_api_settings(*args, **kwargs):setting = kwargs['setting']if setting == 'REST_FRAMEWORK':api_settings.reload()setting_changed.connect(reload_api_settings)

request的源码

################################ request.py ############################################
class Request(object):"""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 therequest content.- authentication_classes(list/tuple). The authentications used to tryauthenticating 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 = requestself.parsers = parsers or ()self.authenticators = authenticators or ()self.negotiator = negotiator or self._default_negotiator()self.parser_context = parser_contextself._data = Emptyself._files = Emptyself._full_data = Emptyself._content_type = Emptyself._stream = Emptyif self.parser_context is None:self.parser_context = {}self.parser_context['request'] = selfself.parser_context['encoding'] = request.encoding or settings.DEFAULT_CHARSETforce_user = getattr(request, '_force_auth_user', None)force_token = getattr(request, '_force_auth_token', None)if force_user is not None or force_token is not None:forced_auth = ForcedAuthentication(force_user, force_token)self.authenticators = (forced_auth,)def _default_negotiator(self):return api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS()@propertydef content_type(self):meta = self._request.METAreturn meta.get('CONTENT_TYPE', meta.get('HTTP_CONTENT_TYPE', ''))@propertydef stream(self):"""Returns an object that may be used to stream the request content."""if not _hasattr(self, '_stream'):self._load_stream()return self._stream@propertydef query_params(self):"""More semantically correct name for request.GET."""return self._request.GET@propertydef data(self):if not _hasattr(self, '_full_data'):self._load_data_and_files()return self._full_data@propertydef user(self):         # 7.2 认证的走到这,实际执行 self._authenticate(),"""Returns the user associated with the current request, as authenticatedby the authentication classes provided to the request."""if not hasattr(self, '_user'):with wrap_attributeerrors():self._authenticate()return self._user@user.setterdef user(self, value):"""Sets the user on the current request. This is necessary to maintaincompatibility with django.contrib.auth where the user property isset 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 = valueself._request.user = value@propertydef auth(self):"""Returns any non-user authentication information associated with therequest, such as an authentication token."""if not hasattr(self, '_auth'):with wrap_attributeerrors():self._authenticate()return self._auth@auth.setterdef auth(self, value):"""Sets any non-user authentication information associated with therequest, such as an authentication token."""self._auth = valueself._request.auth = value@propertydef successful_authenticator(self):"""Return the instance of the authentication instance class that was usedto authenticate the request, or `None`."""if not hasattr(self, '_authenticator'):with wrap_attributeerrors():self._authenticate()return self._authenticatordef _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.POSTself._request._files = self.FILESdef _load_stream(self):"""Return the content body of the request, as a stream."""meta = self._request.METAtry:content_length = int(meta.get('CONTENT_LENGTH', meta.get('HTTP_CONTENT_LENGTH', 0)))except (ValueError, TypeError):content_length = 0if content_length == 0:self._stream = Noneelif not self._request._read_started:self._stream = self._requestelse:self._stream = io.BytesIO(self.body)def _supports_form_parsing(self):"""Return True if this requests supports parsing form data."""form_media = ('application/x-www-form-urlencoded','multipart/form-data')return any([parser.media_type in form_media for parser in self.parsers])def _parse(self):"""Parse the request content, returning a two-tuple of (data, files)May raise an `UnsupportedMediaType`, or `ParseError` exception."""media_type = self.content_typetry:stream = self.streamexcept RawPostDataException:if not hasattr(self._request, '_post'):raise# If request.POST has been accessed in middleware, and a method='POST'# request was made with 'multipart/form-data', then the request stream# will already have been exhausted.if self._supports_form_parsing():return (self._request.POST, self._request.FILES)stream = Noneif stream is None or media_type is None:if media_type and is_form_media_type(media_type):empty_data = QueryDict('', encoding=self._request._encoding)else:empty_data = {}empty_files = MultiValueDict()return (empty_data, empty_files)parser = self.negotiator.select_parser(self, self.parsers)if not parser:raise exceptions.UnsupportedMediaType(media_type)try:parsed = parser.parse(stream, media_type, self.parser_context)except Exception:# If we get an exception during parsing, fill in empty data and# re-raise.  Ensures we don't simply repeat the error when# attempting to render the browsable renderer response, or when# logging the request or similar.self._data = QueryDict('', encoding=self._request._encoding)self._files = MultiValueDict()self._full_data = self._dataraise# Parser classes may return the raw data, or a# DataAndFiles object.  Unpack the result as required.try:return (parsed.data, parsed.files)except AttributeError:empty_files = MultiValueDict()return (parsed, empty_files)def _authenticate(self):          # 7.2 认证时真正执行的地方"""Attempt to authenticate the request using each authentication instancein turn."""for authenticator in self.authenticators:    #  7.2 查找当前配置的self.authenticators,执行里面的authenticate(self)try:                                     #  7.2 最后返回一个元祖,(认证之后的用户,认证的obj)user_auth_tuple = authenticator.authenticate(self)except exceptions.APIException:self._not_authenticated()raiseif user_auth_tuple is not None:self._authenticator = authenticatorself.user, self.auth = user_auth_tuplereturnself._not_authenticated()def _not_authenticated(self):                  # 7.2 如果没有认证,那么返回(None,None)"""Set authenticator, user & authtoken representing an unauthenticated request.Defaults are None, AnonymousUser & None."""self._authenticator = Noneif api_settings.UNAUTHENTICATED_USER:self.user = api_settings.UNAUTHENTICATED_USER()else:self.user = Noneif api_settings.UNAUTHENTICATED_TOKEN:self.auth = api_settings.UNAUTHENTICATED_TOKEN()else:self.auth = Nonedef __getattr__(self, attr):"""If an attribute does not exist on this instance, then we also attemptto proxy it to the underlying HttpRequest object."""try:return getattr(self._request, attr)except AttributeError:return self.__getattribute__(attr)@propertydef DATA(self):raise NotImplementedError('`request.DATA` has been deprecated in favor of `request.data` ''since version 3.0, and has been fully removed as of version 3.2.')@propertydef POST(self):# Ensure that request.POST uses our request parsing.if not _hasattr(self, '_data'):self._load_data_and_files()if is_form_media_type(self.content_type):return self._datareturn QueryDict('', encoding=self._request._encoding)@propertydef FILES(self):# Leave this one alone for backwards compat with Django's request.FILES# Different from the other two cases, which are not valid property# names on the WSGIRequest class.if not _hasattr(self, '_files'):self._load_data_and_files()return self._files@propertydef QUERY_PARAMS(self):raise NotImplementedError('`request.QUERY_PARAMS` has been deprecated in favor of `request.query_params` ''since version 3.0, and has been fully removed as of version 3.2.')def force_plaintext_errors(self, value):# Hack to allow our exception handler to force choice of# plaintext or html error responses.self._request.is_ajax = lambda: value

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/454410.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

-9 逆序输出一个整数的各位数字_leetcode两数相加(大整数相加)

题目来源于leetcode第二题两数相加。题目描述给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。如果,我们将这两个数相加起来,则会返回一个新的链表来…

计算机如何添加管理员权限,电脑使用代码如何添加管理员权限

我们在使用电脑运行某些软件的时候,可能需要用到管理员权限才能运行,通常来说直接点击右键就会有管理员权限,但最近有用户向小编反馈,在需要管理员权限的软件上点击右键没有看到管理员取得所有权,那么究竟该如何才能获…

sql注入问题

${}拼接sql,会引起sql注入,sql注入例如: select * from user where name like ‘%’ or 11 or ‘%’; 这种情况下,论name为什么都可以执行 转载于:https://www.cnblogs.com/mengyinianhua/p/7649325.html

teechart绘制实时曲线_快速学会CAD绘制传输线路图纸

一工具CAD工程设计软件二方法和步骤万事开头难,遇到不懂的知识刚开始都有畏难的情绪,只要有决心学习,诚心想学会一项技能,那学会学好它就只是时间问题了。我们常常面临时间紧、需要快速入门甚至熟练地解决工作中实际情况的问题&am…

使用ajax获取用户所在地的天气

1.要获取用户归属地的天气&#xff0c;首先得获取用户所在的市区&#xff0c; 这里先获取用户的IP&#xff0c;通过IP获取IP的归属地&#xff0c;从而得到用户 地址。 获取客户端ip: js: <scripttype"text/javascript" src"http://pv.sohu.com/cityjson?ieu…

Python 之协程

之前我们学习了线程、进程的概念&#xff0c;了解了在操作系统中进程是资源分配的最小单位,线程是CPU调度的最小单位。按道理来说我们已经算是把cpu的利用率提高很多了。但是我们知道无论是创建多进程还是创建多线程来解决问题&#xff0c;都要消耗一定的时间来创建进程、创建线…

ip变换器苹果系统_加密锁能为高铁做什么?铁路电力变换器系统告诉您

代表国之重器的高铁&#xff0c;是怎样保护他们在软件上投资的专有技术不被仿冒、逆向工程和篡改呢&#xff1f;与一般的软件保护加密不同&#xff0c;高铁运行中的实时控制器对物理环境有着严苛的要求&#xff0c;如铁路电力变换器系统&#xff0c;须满足典型工业应用的扩展温…

zxing .net 多种条码格式的生成

下载地址&#xff1a;http://zxingnet.codeplex.com/ zxing.net是.net平台下编解条形码和二维码的工具&#xff0c;使用非常方便。 本文主要说明一下多种类型条码的生成。 适用的场景&#xff0c;标签可视化设计时&#xff0c;自定义条码类型&#xff0c;预览。 遍历zxing支持的…

k8s dashboard_windows10 部署 docker+k8s 集群

下面是经过踩坑之后的 windows10 单机部署 docker k8s 步骤&#xff0c;其中有几处比较关键的地方需要注意&#xff0c;后面加粗标注&#xff0c;下面就开始吧&#xff01;0、下载cmder在 windows 上有一个趁手的命令行工具非常有必要&#xff0c;推荐 Cmder&#xff0c;下面是…

Python 之网络编程基础

套接字&#xff08;socket&#xff09;初使用 基于TCP协议的socket tcp是基于链接的&#xff0c;必须先启动服务端&#xff0c;然后再启动客户端去链接服务端 server端 import socket sk socket.socket() sk.bind((127.0.0.1,8898)) # 把地址绑定到套接字 sk.listen() …

面试之网络编程和并发

1、简述 OSI 七层协议。 物理层&#xff1a;主要基于电器特性发送高低电压(1、0)&#xff0c;设备有集线器、中继器、双绞线等&#xff0c;单位&#xff1a;bit 数据链路层&#xff1a;定义了电信号的分组方式&#xff0c;设备&#xff1a;交换机、网卡、网桥&#xff0c;单位&…

redis 远程主机强迫关闭了一个现有的连接_记一次Redis+Getshell经验分享

你是我患得患失的梦&#xff0c;我是你可有可无的人&#xff0c;毕竟这穿越山河的箭&#xff0c;刺的都是用情之疾的人。前言&#xff1a;当我们接到一个授权渗透测试的时候&#xff0c;常规漏洞如注入、文件上传等尝试无果后&#xff0c;扫描端口可能会发现意外收获。知己知彼…

无线连接 服务器,服务器无线远程连接

服务器无线远程连接 内容精选换一换华为云帮助中心&#xff0c;为用户提供产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题、视频帮助等技术文档&#xff0c;帮助您快速上手使用华为云服务。使用Mac版Microsoft Remote Desktop工具&#xff0c;远程连接W…

IO模型

IO模型介绍 传统的网络IO模型包括五种&#xff1a; blocking IO 阻塞IOnonblocking IO 非阻塞IOIO multiplexing IO多路复用signal driven IO 信号驱动IOasynchronous IO 异步IO 由于signal driven IO&#xff08;信号驱动IO&#xff09;在实际中…

重温数据结构:树 及 Java 实现(转)

转自&#xff1a;http://blog.csdn.net/u011240877/article/details/53193877 读完本文你将了解到&#xff1a; 什么是树树的相关术语 根节点父亲节点孩子节点叶子节点如上所述节点的度树的度节点的层次树的高度树的深度树的两种实现 数组表示链表表示的节点树的几种常见分类及…

Powershell检测AD账户密码过期时间并邮件通知

脚本主要实现了两个功能 &#xff1a; 一能判断账户密码的过期时间并通过邮件通知到账户&#xff1b; 二是将这些即将过期的账户信息累计通知到管理员。 脚本如下&#xff1a; 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051…

js list删除指定元素_vue.js

vue.js 中M V MV代表哪一部分 <插值表达式&#xff08;v-cloak v-text v-html v-bind&#xff08;缩写是:&#xff09; v-on&#xff08;缩写是&#xff09; v-model v-for v-if v-show &#xff09;<body><div id"app"><!-- 使用 v-cloak 能够解决…

我们的系统检测到您的计算机网络中存在异常流量_如何建立我们的网络防线?入侵检测,确保我们的网络安全...

目前我们的网络安全趋势日益严峻&#xff0c;那么如何利用入侵检测系统确保我的网络安全呢&#xff1f;入侵检测又是什么呢&#xff1f;网络安全入侵检测技术是为保证计算机系统的安全&#xff0c;而设计与配置的一种能够及时发现并报告系统中未授权或异常现象的技术&#xff0…

mybatis $和#源代码分析

JDBC中&#xff0c;主要使用两种语句&#xff0c;一种是支持参数化和预编译的PreparedStatement,支持原生sql,支持设置占位符&#xff0c;参数化输入的参数&#xff0c;防止sql注入攻击&#xff0c;在mybatis的mapper配置文件中&#xff0c;我们通过使用#和$告诉mybatis我们需要…

git 命令详解和常见问题解决

功能一 提交&#xff1a;1:git init # 初始化&#xff0c;表示即将对当前文件夹进行版本控制2:git status # 查看Git当前状态&#xff0c;如&#xff1a;那些文件被修改过、那些文件还未提交到版本库等。3:git add . # 添加当前目录下所有文件到版本…