Django rest framework 소스 읽기 (1) -- - 요청 프로세스

23351 단어 Django 소스 읽기
CBV를 실례화하고 이 대상의 디스패치 방법을 호출합니다
  • 요청이 도착했을 때 먼저 CBV에 정의된 디스패치에 의해 처리됩니다.
  •   # 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):
            """
            `.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)
            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
    

    첫 번째 단계에서는 WSGIRequest 객체를 rest 로 캡슐화합니다.framework.request.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(),   #  get  
                authenticators=self.get_authenticators(), #    
                negotiator=self.get_content_negotiator(), #     
                parser_context=parser_context
            )
    
  • initialize_request 방법 중 리퀘스트를 처리한 방법이 있는데 뷰의 값은self이고 UsersView라는 대상을 가리키기 때문에 getparser_context 방법은 UsersView라는 종류를 봉인해서 되돌려줍니다. 그래서 getparser_context 방법은 마지막으로 현재 대상과 현재 대상이 전하는 매개 변수를 되돌려줍니다.
  •     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', {})
            }
    
  • getauthenticators 방법에서 검증 규칙을 봉인한authenticator 대상을 획득하고 본질적으로 다음과 같은 절차를 거친다
  •     def get_authenticators(self):
            """
            Instantiates and returns the list of authenticators that this view can use.
            """
            
            return [auth() for auth in self.authentication_classes]
        authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
        api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)    
    
    DEFAULTS = {
    	...
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.SessionAuthentication',
            'rest_framework.authentication.BasicAuthentication'
        ),
    }
    

    두 번째, 인티리얼이라는 방법을 다시 보도록 하겠습니다.
  • 먼저 get 실행format_suffix는 클라이언트가 보낸 URL의 접미사를 가져와performcontent_이 방법의 주요 역할은 내용 선택을 실행하고 수신된 정보를 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)
    
            # Perform content negotiation and store the accepted info on the request
            neg = self.perform_content_negotiation(request)
            request.accepted_renderer, request.accepted_media_type = neg
            # Determine the API version, if versioning is in use.
            #   url      ,            ,      
            version, scheme = self.determine_version(request, *args, **kwargs)
            request.version, request.versioning_scheme = version, scheme
    
            # Ensure that the incoming request is permitted
            #       ,                .perform_authentication             
            self.perform_authentication(request)
            #         ,           url      .                 ,      .
            self.check_permissions(request)
            # check_throttles                       ,                 ,        
            self.check_throttles(request)
    

    세 번째 단계, initial 이 방법 실행 완료 후
            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
    
  • initial 방법을 실행하기 전에try/except 방법을 사용하여 이상 처리를 하였습니다. initial 방법을 실행할 때 오류가 발생하면handleexception은 initial 방법이 던진 이상을 처리하고 정확한 응답 정보를 되돌려줍니다. 만약 initial 방법이 실행되고 던진 이상이 없으면 Request입니다.method.lower는 요청한 방법을 소문자로 변환하고, UsersView 클래스의 get이나post 등 사용자 정의 방법을 반사적으로 실행한 다음 응답 정보를 되돌려줍니다.

  • 4단계,finalize 실행response 방법으로 최종 응답 정보를 클라이언트의 브라우저에 되돌려줍니다
        def finalize_response(self, request, response, *args, **kwargs):
            """
            Returns the final response object.
            """
            # Make the error obvious if a proper response is not returned
            assert 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 = neg
    
                response.accepted_renderer = request.accepted_renderer
                response.accepted_media_type = request.accepted_media_type
                response.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] = value
    
            return response
    

    요약 요청 프로세스
    1. 서비스 측에 도착을 요청하고 WSGI와 중간부품을 거쳐 루트 시스템에 도착한다.라우팅 시스템에서 구성된 CBV 또는 FBV의 dispatch 메서드를 실행합니다. 3.디스패치 방법에서 Request 방법은 봉인되어 해석기, 인증 방법 및 선택기 등 방법이 추가되었습니다. 4.그리고 initial 방법 5를 실행합니다.버전 취득, 인증 조작, 권한 조작과 절전 조작 6.마지막으로 사용자 정의 get,post,push,delete 등 사용자 정의 방법을 실행합니다.initial 방법을 실행하기 전에try를 통해 발생할 수 있는 이상을 포착합니다.이상이 발생하면handle포획된 이상을 exception 방법으로 처리합니다.이상이 발생하든지 않든지 마지막 반환값은finalize응답 내용을 처리하기 위한 response 방법
    참조 링크
    Django REST 프레임워크의 요청 라이프 사이클 소스 분석

    좋은 웹페이지 즐겨찾기