Django框架学习-请求到响应的过程

1、目录结构

2、Django基本流程

1、用户浏览器发起http请求;
2、请求首先到达 Request Middleware 中间件,它能在views 收到请求前对Request消息内容进行处理,发送响应;
3、urls.py 中的 URLConf 对收到请求的url进行匹配,找到相应的视图处理函数或视图类;
4、在View收到请求之前,View Middlewares 被调用, 可以进行一些预处理;
5、视图函数或视图类被调用;
6、视图函数可能访问模型数据,也可能调用 form 生成表单对象;
7、所有 model-to-DB 的交互都通过 manager 对象来完成;
8、Views 可通以通过context 对象来添加更多传给模板的内容;
9、Views 将 context 上下文数据传给模板进行渲染;
  模板层使用 Filter与 Tags 渲染输出;
  模板层将渲染结果 传回给 视图层;
  视图层发送HTTPResponse 给Response Middlerwares 中间件;
  Response middlewares中间件可以向Response 消息添加额外内容,或者用1个新消息替代 wsgi 网关发送 response 给用户浏览器;

3、Django代码层面启动流程

Django的运行是通过WSGI server运行起来的,

core\wsgi.py

  • 使用settings.py加载配置项;
  • 根据用户配置的INSTALLED_APPS,依次导入,并导入相应的models;
 1 import django
 2 from django.core.handlers.wsgi import WSGIHandler
 3 
 4 def get_wsgi_application():
 5     """
 6     The public interface to Django's WSGI support. Return a WSGI callable.
 7 
 8     Avoids making django.core.handlers.WSGIHandler a public API, in case the
 9     internal WSGI implementation changes or moves in the future.
10     """
11     django.setup(set_prefix=False)
12     return WSGIHandler()

其次,启动一个WSGIHandler用来接收并处理用户请求,Django的核心处理结构都在load_middleware中完成,会根据middleware建立一个层级的调用处理链;

core\handlers\wsgi.py

 1 class WSGIHandler(base.BaseHandler):
 2     request_class = WSGIRequest
 3 
 4     def __init__(self, *args, **kwargs):
 5         super().__init__(*args, **kwargs)
 6         self.load_middleware()
 7 
 8     def __call__(self, environ, start_response):
 9         set_script_prefix(get_script_name(environ))
10         signals.request_started.send(sender=self.__class__, environ=environ)
11         request = self.request_class(environ)
12         response = self.get_response(request)
13 
14         response._handler_class = self.__class__
15 
16         status = "%d %s" % (response.status_code, response.reason_phrase)
17         response_headers = [
18             *response.items(),
19             *(("Set-Cookie", c.output(header="")) for c in response.cookies.values()),
20         ]
21         start_response(status, response_headers)
22         if getattr(response, "file_to_stream", None) is not None and environ.get(
23             "wsgi.file_wrapper"
24         ):
25             # If `wsgi.file_wrapper` is used the WSGI server does not call
26             # .close on the response, but on the file wrapper. Patch it to use
27             # response.close instead which takes care of closing all files.
28             response.file_to_stream.close = response.close
29             response = environ["wsgi.file_wrapper"](
30                 response.file_to_stream, response.block_size
31             )
32         return response

4、WSGI

WSGI:全称是Web Server Gateway Interface,用于描述web服务器如何与web应用通信的规范。

当客户端发送一次请求后,最先处理请求的实际上是 web 服务器(即经常说的 nginx、Apache 这类),然后web服务器再把请求交给web应用程序(如Django)处理,这中间的中介就是WSGI,它把 web 服务器和 web 框架 (Django) 连接起来。

  • WSGI server 负责从客户端接收请求,将request转发给application,将application返回的response返回给客户端;
  • WSGI application 接收由server转发的request,处理请求,并将处理结果返回给server。application中可以包括多个栈式的中间件(middlewares),这些中间件需要同时实现server与application;

5、中间件

位于Web服务器端和Web应用之间的,它可以添加额外的功能。比如,对来自用户的数据进行预处理,然后发送给应用;在应用将响应负载返回给用户之前,对结果数据进行一些最终的调整。通俗一点,Django中,中间件能够帮我们准备好request这个对象,然后应用可以直接使用request对象获取到各类数据,也帮我们将response添加头部,状态码等。

settings.py文件

1 MIDDLEWARE = [
2     'django.middleware.security.SecurityMiddleware',
3     'django.contrib.sessions.middleware.SessionMiddleware',
4     'django.middleware.common.CommonMiddleware',
5     'django.middleware.csrf.CsrfViewMiddleware',                      # 跨站请求保护机制
6     'django.contrib.auth.middleware.AuthenticationMiddleware',
7     'django.contrib.messages.middleware.MessageMiddleware',
8     'django.middleware.clickjacking.XFrameOptionsMiddleware',
9 ]

 当Django接受到一个请求,会初始化一个WSGIHandler,可以在项目下的wsgi.py文件进行跟踪。

Django 的中间件类至少含有以下四个方法中的一个:
process_request、 process_view、process_exception、process_response。
WSGIHandler通过load_middleware将这些方法分别添加到_request_middleware、_view_middleware、 _exception_middleware和_response_middleware 四个列表中。

责任链结构

所有的middleware都继承于MiddlewaMixin这个类,这个类实现了嵌套的层级调用逻辑,即责任链模式。

process_request

AuthenticationMiddleware 只有process_request,返回None或者HTTPResponse对象【返回None时,WSGIHandler会继续加载 process_request 中的方法】,说明它只在 request 这一步处理流入和流出 Django 应用的数据流。这个中间件会首先验证会话中间件是否被使用,然后通过调用 get_user 函数来设置用户。
 1 def get_user(request):
 2     if not hasattr(request, "_cached_user"):
 3         request._cached_user = auth.get_user(request)
 4     return request._cached_user
 5 
 6 class AuthenticationMiddleware(MiddlewareMixin):
 7     def process_request(self, request):
 8         if not hasattr(request, "session"):
 9             raise ImproperlyConfigured(
10                 "The Django authentication middleware requires session "
11                 "middleware to be installed. Edit your MIDDLEWARE setting to "
12                 "insert "
13                 "'django.contrib.sessions.middleware.SessionMiddleware' before "
14                 "'django.contrib.auth.middleware.AuthenticationMiddleware'."
15             )
16         request.user = SimpleLazyObject(lambda: get_user(request))

路由

 setting.py中ROOT_URLCONF,它指向urls.py文件,是url和view视图函数之间的映射表。

1 ROOT_URLCONF = 'djangoProject.urls'

process_view

经过url的匹配,会获得视图函数和相关参数,在调用view函数之前,Django会先加载_view_middleware中的各个process_view方法。

举例:CsrfViewMiddleware中的process_view方法功能,当 CSRF cookies 出现时,process_view 方法将会返回 None, 视图函数将会继续的执行。否则请求将会被拒绝,处理流程将会被'短路',会生成一个错误的信息。

 1 class CsrfViewMiddleware(MiddlewareMixin):
 2     def process_view(self, request, callback, callback_args, callback_kwargs):
 3         if getattr(request, "csrf_processing_done", False):
 4             return None
 5 
 6         if getattr(callback, "csrf_exempt", False):
 7             return None
 8 
 9         if request.method in ("GET", "HEAD", "OPTIONS", "TRACE"):
10             return self._accept(request)
11 
12         if getattr(request, "_dont_enforce_csrf_checks", False):
13             return self._accept(request)
14 
15         if "HTTP_ORIGIN" in request.META:
16             if not self._origin_verified(request):
17                 return self._reject(
18                     request, REASON_BAD_ORIGIN % request.META["HTTP_ORIGIN"]
19                 )
20         elif request.is_secure():
21             try:
22                 self._check_referer(request)
23             except RejectRequest as exc:
24                 return self._reject(request, exc.reason)
25 
26         try:
27             self._check_token(request)
28         except RejectRequest as exc:
29             return self._reject(request, exc.reason)
30 
31         return self._accept(request)

进入视图函数

满足三个条件:

(1)必须是可调用的;

(2)必须接受一个HTTPRequest对象作为第一个位置参数;

(3)必须返回一个HTTPResponse对象,或者抛出一个异常;

process_exception

如果视图函数抛出一个异常,WSGIHandler将会循环遍历_exception_middleware 列表,这些方法按照相反的顺序执行,从 settings.py 里面列出来的最后一个中间件到第一个。

如果一个异常被抛出,处理过程将会被短路,其他的 process_exception 将不会被执行。

process_response

此阶段,我们得到了一个 HTTPResponse 对象,这个对象可能是 process_view 返回的,也可能是视图函数返回的。现在我们将循环访问响应中间件。这是中间件调整数据的最后的机会。执行的顺序是从内向外执行。

举例:CsrfViewMiddleware在response中设置csrf cookies;

1 class CsrfViewMiddleware(MiddlewareMixin):
2     def process_response(self, request, response):
3         if request.META.get("CSRF_COOKIE_NEEDS_UPDATE"):
4             self._set_csrf_cookie(request, response)
5             request.META["CSRF_COOKIE_NEEDS_UPDATE"] = False
6 
7         return response

 

posted @ 2023-07-04 17:42  最咸的鱼  阅读(376)  评论(0编辑  收藏  举报