Django框架架构和Request/Response处理流程(转)

一、 处理过程的核心概念

如下图所示django的总览图,整体上把握以下django的组成:

django整体架构图

核心在于中间件middleware,django所有的请求、返回都由中间件来完成。

中间件,就是处理HTTP的request和response的,类似插件,比如有Request中间件、view中间件、response中间件、exception中间件等,Middleware都需要在 “project/settings.py” 中 MIDDLEWARE_CLASSES 的定义。大致的程序流程图如下所示:

整体流程

首先,Middleware都需要在 “project/settings.py” 中 MIDDLEWARE_CLASSES 的定义, 一个HTTP请求,将被这里指定的中间件从头到尾处理一遍,暂且称这些需要挨个处理的中间件为处理链,如果链中某个处理器处理后没有返回response,就把请求传递给下一个处理器;如果链中某个处理器返回了response,直接跳出处理链由response中间件处理后返回给客户端,可以称之为短路处理。

二、 中间件中的方法

Django处理一个Request的过程是首先通过中间件,然后再通过默认的URL方式进行的。我们可以在Middleware这个地方把所有Request拦截住,用我们自己的方式完成处理以后直接返回Response。因此了解中间件的构成是非常必要的。

 

Initializer: init(self)

出于性能的考虑,每个已启用的中间件在每个服务器进程中只初始化一次。也就是说 init() 仅在服务进程启动的时候调用,而在针对单个request处理时并不执行。

对一个middleware而言,定义 init() 方法的通常原因是检查自身的必要性。如果 init() 抛出异常 django.core.exceptions.MiddlewareNotUsed ,则Django将从middleware栈中移出该middleware。

在中间件中定义 init() 方法时,除了标准的 self 参数之外,不应定义任何其它参数。

 

Request预处理函数: process_request(self, request)

这个方法的调用时机Django接收到request之后,但仍未解析URL以确定应当运行的view之前。Django向它传入相应的 HttpRequest 对象,以便在方法中修改。

process_request() 应当返回 None 或 HttpResponse 对象.

如果返回 None , Django将继续处理这个request,执行后续的中间件, 然后调用相应的view.

如果返回 HttpResponse 对象,Django 将不再执行任何其它的中间件(无视其种类)以及相应的view。 Django将立即返回该 HttpResponse .

 

View预处理函数: process_view(self, request, callback, callback_args, callback_kwargs)

这个方法的调用时机在Django执行完request预处理函数并确定待执行的view之后,但view函数实际执行之前

request:HttpRequest 对象。

callback:Django将调用的处理request的python函数. 这是实际的函数对象本身, 而不是字符串表述的函数名。

args:将传入view的位置参数列表,但不包括 request 参数(它通常是传入view的第一个参数)
kwargs:将传入view的关键字参数字典.

如同 process_request() , process_view() 应当返回 None 或 HttpResponse 对象。

如果返回 None , Django将继续处理这个 request ,执行后续的中间件, 然后调用相应的view

如果返回 HttpResponse 对象,Django 将不再执行 任何 其它的中间件(不论种类)以及相应的view。Django将立即返回

 

Response后处理函数: process_response(self, request, response)

这个方法的调用时机在Django执行view函数并生成response之后

该处理器能修改response的内容;一个常见的用途是内容压缩,如gzip所请求的HTML页面。

这个方法的参数相当直观: request 是request对象,而 response 则是从view中返回的response对象。

process_response() 必须 返回 HttpResponse 对象. 这个response对象可以是传入函数的那一个原始对象(通常已被修改),也可以是全新生成的。

 

Exception后处理函数: process_exception(self, request, exception)

这个方法只有在request处理过程中出了问题并且view函数抛出了一个未捕获的异常时才会被调用。这个钩子可以用来发送错误通知,将现场相关信息输出到日志文件, 或者甚至尝试从错误中自动恢复

这个函数的参数除了一贯的 request 对象之外,还包括view函数抛出的实际的异常对象 exception 。

process_exception() 应当返回 None 或 HttpResponse 对象.

如果返回 None , Django将用框架内置的异常处理机制继续处理相应request。

如果返回 HttpResponse 对象, Django 将使用该response对象,而短路框架内置的异常处理机制

以下几章会详细介绍该机制。

 

 

三、 Django目录结构

dsf

conf

主要有两个作用:1) 处理全局配置, 比如数据库、加载的应用、 MiddleWare等 2) 处理urls配置, 就是url与view的映射关系。

contrib (贡献)

由Django的开发者贡献的功能模块,不过既然都已经随版本发布, 就表示是官方的。

core

Django的核心处理库,包括url分析、处理请求、缓存等,其中处理请求是核心了,比如处理fastcgi就是由wsgi.py处理。

db

顾名思义,处理与数据库相关的,就是ORM。

dispatch (分派,派遣)

其实这不是Django原创,是pydispatch库,主要处 理消费者-工作者模式。

forms && newforms && oldforms

处理html的表单,不用多介绍。

middleware

中间件,就是处理HTTP的request和response的,类似插件。比 如默认的common中间件的一个功能:当一个页面没有找对对应的 pattern时, 会自定加上‘/’重新处理。比如访问/blog时,而定义的pattern是‘^blog/$’, 所以找不到对应的pattern,会自动再用/blog/查找,当然前提是 APPEND_SLASH=True。

template

Django的模板

templatetags

处理Application的tag的wrapper,就是将INSTALLED_APPS中 所有的templatetags目录添加到 django.templatetags目录中,则当使用 {{load blog}}记载tag时,就可以使用 import django.templatetags.blog 方式加载了。不过这有一个问题,如果其他Application目录中也有blog.py, 这会加载第一个出现blog.py的tag。其实在 Django中,有许多需要处理重名 的地方,比如template,需要格外小心,这个后续在介绍。

utils

公共库,很多公用的类都在放在这里。

views

最基本的view方法。

 

四、 Django 术语

在应用 Django 的时候,我们经常听到一些术语:

Project

指一个完整的Web服务,一般由多个模块组成。

Application

可以理解为模块,比如用户管理、博客管理等,包含了数据的组成和数据的显示,Applicaiton都需要在 “project/settings.py” 中 INSTALLED_APPS 的定义。

Middleware

就是处理request和response的插件, Middleware都需要在 “project/settings.py” 中 MIDDLEWARE_CLASSES 的定义。

Loader

模板加载器, 其实就是为了读取 Template 文件的类,默认的有通过文件系统加载和在 “Application/templates” 目录中加载,Loader都需要在 “project/settings.py” 中 TEMPLATE_LOADERS 的定义。

 

 

五、 处理流程

其实和其他Web框架一样,HTTP处理的流程大致相同,

Django处理一个Request的过程是首先通过中间件,然后再通过默认的URL方式进行的。我们可以在Middleware这个地方把所有Request拦截住,用我们自己的方式完成处理以后直接返回Response。

1. 加载配置

Django的配置都在 “Project/settings.py” 中定义,可以是Django的配置,也 可以是自定义的配置,并且都通过 django.conf.settings 访问,非常方便。

2. 启动

最核心动作的是通过 django.core.management.commands.runfcgi 的 Command 来启动,它运行 django.core.servers.fastcgi 中的 runfastcgi , runfastcgi 使用了 flup 的 WSGIServer 来启动 fastcgi 。而 WSGIServer 中携带了 django.core.handlers.wsgi 的 WSGIHandler 类的一个实例,通过 WSGIHandler来处理由Web服务器(比如Apache,Lighttpd等)传过来的请求,此 时才是真正进入Django的世界。

3. 处理 Request

当有HTTP请求来时, WSGIHandler 就开始工作了,它从 BaseHandler 继承而来。 WSGIHandler 为每个请求创建一个 WSGIRequest 实例,而 WSGIRequest 是从 http.HttpRequest 继承而来。接下来就开始创建 Response 了.

4. 创建Response

BaseHandler 的 get_response 方法就是根据 request 创建 response , 而 具体生成 response 的动作就是执行 urls.py 中对应的view函数了,这也是 Django可以处理“友好URL”的关键步骤,每个这样的函数都要返回一个 Response 实例。此时一般的做法是通过 loader 加载 template 并生成页面内 容,其中重要的就是通过 ORM 技术从数据库中取出数据,并渲染到 Template 中,从而生成具体的页面了

5. 处理Response

Django 返回 Response 给 flup , flup 就取出 Response 的内容返回给 Web 服务器,由后者返回给浏览器。

总之, Django 在 fastcgi 中主要做了两件事:处理 Request 和创建 Response , 而它们对应的核心就是“urls分析”、“模板技术”和“ORM技术”

12

如图所示,一个HTTP请求,首先被转化成一个HttpRequest对象,然后该对象被传递给Request中间件处理,如果该中间件返回了Response,则直接传递给Response中间件做收尾处理。否则的话Request中间件将访问URL配置,确定哪个view来处理,在确定了哪个view要执行,但是还没有执行该view的时候,系统会把request传递给View中间件处理器进行处理,如果该中间件返回了Response,那么该Response直接被传递给Response中间件进行后续处理,否则将执行确定的View函数处理并返回Response,在这个过程中如果引发了异常并抛出,会被Exception中间件处理器进行处理。

 

转自:http://www.crazyant.net/1001.html

暂无评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注