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.pswp.cn/news/454410.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454410.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454410.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

-9 逆序輸出一個整數的各位數字_leetcode兩數相加(大整數相加)

題目來源于leetcode第二題兩數相加。題目描述給出兩個非空的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照逆序的方式存儲的,并且它們的每個節點只能存儲一位數字。如果,我們將這兩個數相加起來,則會返回一個新的鏈表來…

計算機如何添加管理員權限,電腦使用代碼如何添加管理員權限

我們在使用電腦運行某些軟件的時候,可能需要用到管理員權限才能運行,通常來說直接點擊右鍵就會有管理員權限,但最近有用戶向小編反饋,在需要管理員權限的軟件上點擊右鍵沒有看到管理員取得所有權,那么究竟該如何才能獲…

mysql選擇數據庫創建數據庫

MySQL 選擇數據庫 在你連接到 MySQL 數據庫后,可能有多個可以操作的數據庫,所以你需要選擇你要操作的數據庫。 從命令提示窗口中選擇MySQL數據庫 在 mysql> 提示窗口中可以很簡單的選擇特定的數據庫。你可以使用SQL命令來選擇指定的數據庫。 實例 以下…

英語面試技巧以及準備工作

如果你提前知道了電話面試的時間,則可以在面試時把簡歷、coverletter放在你旁邊的桌子上,直接運用里面的句子回答問題。一些基本的問題,你可以事先準備好答案。通常,在電話英語面試的時候會提道:  please tell me som…

sql注入問題

${}拼接sql,會引起sql注入,sql注入例如: select * from user where name like ‘%’ or 11 or ‘%’; 這種情況下,論name為什么都可以執行 轉載于:https://www.cnblogs.com/mengyinianhua/p/7649325.html

Python 面向對象之雙下方法,內置函數

isinstance和issubclass isinstance(obj,cls) # 檢查是否obj是否是類 cls 的對象 class Foo(object):passobj Foo()isinstance(obj, Foo) # ture issubclass(sub, super) # 檢查sub類是否是 super 類的派生類 class Foo(object):passclass Bar(Foo):passissubclass…

teechart繪制實時曲線_快速學會CAD繪制傳輸線路圖紙

一工具CAD工程設計軟件二方法和步驟萬事開頭難,遇到不懂的知識剛開始都有畏難的情緒,只要有決心學習,誠心想學會一項技能,那學會學好它就只是時間問題了。我們常常面臨時間緊、需要快速入門甚至熟練地解決工作中實際情況的問題&am…

彝文計算機,試論計算機彝文字符編碼的轉換.pdf

試論計算機彝文字符編碼的轉換.pdf第17卷 第1期 云南民族大學學報(自然科學版) V01.17 No.12008年1月 Journal of Yunnan Nationalities University(Natural Sciences Edition) Jan.2o08試論計算機彝文字符編碼的轉換李金發(紅河學院人文學院…

ActiveMQ(07):ActiveMQ結合Spring開發--建議

1、Camel框架支持大量的企業集成模式,可以大大簡化集成組件間的大量服務和復雜的消息流。而Spring框架更注重簡單性,僅僅支持基本的最佳實踐。 2、Spring消息發送的核心架構是JmsTemplate,隔離了像打開、關閉Session和Producer的繁瑣操作&…

使用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;須滿足典型工業應用的擴展溫…

華為服務器ibmc怎么裝系統,華為服務器安裝操作系統

《華為服務器安裝操作系統》由會員分享&#xff0c;可在線閱讀&#xff0c;更多相關《華為服務器安裝操作系統(11頁珍藏版)》請在人人文庫網上搜索。1、華為服務器安裝操作系統 1把網線接到服務器管理口上&#xff0c;2288服務器管理口在服務器背后中下 部位置&#xff0c;有Mg…

英語面試(自我介紹,電話面試..)

大凡找工作的人&#xff0c;都有對面試的擔心&#xff0c;而英語面試最令人頭痛。面試氣氛總是緊張的&#xff0c;一緊張就容易出錯&#xff0c;中文“臺詞”都會結巴&#xff0c;何況英語&#xff01; 可俗話說&#xff0c;養兵千日&#xff0c;用兵一時&#xff0c;學了那么多…

服務端渲染與 Universal React App

隨著 Webpack 等前端構建工具的普及&#xff0c;客戶端渲染因為其構建方便&#xff0c;部署簡單等方面的優勢&#xff0c;逐漸成為了現代網站的主流渲染模式。而在剛剛發布的 React v16.0 中&#xff0c;改進后更為優秀的服務端渲染性能作為六大更新點之一&#xff0c;被 React…

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() …

ajax on ture,細數Ajax請求中的async:false和async:true的差異

實例如下&#xff1a;function test(){var temp"00";$.ajax({async: false,type : "GET",url : userL_checkPhone.do,complete: function(msg){alert(complete);},success : function(data) {alert(success);tempdata;temp"aa";}});alert(temp);…

阿里云郵箱登錄日志中有異地IP登錄是怎么回事?該怎么辦?

注意&#xff0c;請先到阿里云官網 領取幸運券&#xff0c;除了價格上有很多優惠外&#xff0c;還可以參與抽獎。詳見&#xff1a;https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode2a7uv47d&utm_source2a7uv47d以下可能&#xff1a;1、您的郵…