django 처리 클라이언트 요청 프로세스

5844 단어
앞에서 분석한 바와 같이 클라이언트가 http 요청을 보낼 때django 처리 함수는 다음과 같다.
 def __call__(self, environ, start_response):
        set_script_prefix(get_script_name(environ))
        signals.request_started.send(sender=self.__class__, environ=environ)
        try:
            request = self.request_class(environ)
        except UnicodeDecodeError:
            logger.warning(
                'Bad Request (UnicodeDecodeError)',
                exc_info=sys.exc_info(),
                extra={
                    'status_code': 400,
                }
            )
            response = http.HttpResponseBadRequest()
        else:
            response = self.get_response(request)

        response._handler_class = self.__class__

        status = '%d %s' % (response.status_code, response.reason_phrase)
        response_headers = [(str(k), str(v)) for k, v in response.items()]
        for c in response.cookies.values():
            response_headers.append((str('Set-Cookie'), str(c.output(header=''))))
        start_response(force_str(status), response_headers)
        if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
            response = environ['wsgi.file_wrapper'](response.file_to_stream)
        return response

먼저 환경 디렉터리에서 스크립트 디렉터리 접두사 가져오기;signals.request_started.send(sender=self. class,environ=environ)은 Request 를 시작합니다.started 신호 이벤트,django가 제공하는 사용자 정의 Request 처리 전에 해야 할 일의 입구에 사용자가 추가할 수 있습니다. 이 때 실행됩니다.self.request_class는 WSGIRequest이기 때문에 Request는 environ을 사용하여 초기화된 WSGIRequest 대상입니다.
def __init__(self, environ):
        script_name = get_script_name(environ)
        path_info = get_path_info(environ)
        if not path_info:
            # Sometimes PATH_INFO exists, but is empty (e.g. accessing
            # the SCRIPT_NAME URL without a trailing slash). We really need to
            # operate as if they'd requested '/'. Not amazingly nice to force
            # the path like this, but should be harmless.
            path_info = '/'
        self.environ = environ
        self.path_info = path_info
        # be careful to only replace the first slash in the path because of
        # http://test/something and http://test//something being different as
        # stated in http://www.ietf.org/rfc/rfc2396.txt
        self.path = '%s/%s' % (script_name.rstrip('/'),
                               path_info.replace('/', '', 1))
        self.META = environ
        self.META['PATH_INFO'] = path_info
        self.META['SCRIPT_NAME'] = script_name
        self.method = environ['REQUEST_METHOD'].upper()
        self.content_type, self.content_params = cgi.parse_header(environ.get('CONTENT_TYPE', ''))
        if 'charset' in self.content_params:
            try:
                codecs.lookup(self.content_params['charset'])
            except LookupError:
                pass
            else:
                self.encoding = self.content_params['charset']
        self._post_parse_error = False
        try:
            content_length = int(environ.get('CONTENT_LENGTH'))
        except (ValueError, TypeError):
            content_length = 0
        self._stream = LimitedStream(self.environ['wsgi.input'], content_length)
        self._read_started = False
        self.resolver_match = None

get 사용response가response로 되돌아온 후 상태 코드와 응답 헤더를 가져와 매개 변수로 start 호출합니다응답체를 되돌려줍니다.
다음은 시스템이 Request를 어떻게 처리하고 Response로 되돌아오는지 살펴보겠습니다.
    def get_response(self, request):
        """Return an HttpResponse object for the given HttpRequest."""
        # Setup default url resolver for this thread
        set_urlconf(settings.ROOT_URLCONF)

        response = self._middleware_chain(request)

        # This block is only needed for legacy MIDDLEWARE_CLASSES; if
        # MIDDLEWARE is used, self._response_middleware will be empty.
        try:
            # Apply response middleware, regardless of the response
            for middleware_method in self._response_middleware:
                response = middleware_method(request, response)
                # Complain if the response middleware returned None (a common error).
                if response is None:
                    raise ValueError(
                        "%s.process_response didn't return an "
                        "HttpResponse object. It returned None instead."
                        % (middleware_method.__self__.__class__.__name__))
        except Exception:  # Any exception should be gathered and handled
            signals.got_request_exception.send(sender=self.__class__, request=request)
            response = self.handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())

        response._closable_objects.append(request)

        # If the exception handler returns a TemplateResponse that has not
        # been rendered, force it to be rendered.
        if not getattr(response, 'is_rendered', True) and callable(getattr(response, 'render', None)):
            response = response.render()

        if response.status_code == 404:
            logger.warning(
                'Not Found: %s', request.path,
                extra={'status_code': 404, 'request': request},
            )

        return response
set_urlconf는 이 라인에서 기본 URL 분해기를 시작합니다.self.middleware_리퀘스트 (Request) 는 이전에 설명한 모든 처리 과정을 미리 압축하는 곳입니다. 이 때 매개 변수 리퀘스트 호출을 사용하면 모든 사용자가 설정한 중간부품 방법을 순서대로 호출한 다음에 URL에 대응하는view 함수를 가져오고view 관련 중간부품을 사용한 후 사용자 정의view 함수에 들어가서 처리하고response로 돌아갑니다.그리고response와 관련된 중간부품 처리를 호출한 다음response를 되돌려줍니다.

좋은 웹페이지 즐겨찾기