web 框架的设计,将每一个资源地址映射到一个处理逻辑。这篇文章将讲述 django 中对请求的解析处理,及处理结果的返回。
视图函数
资源地址对应的处理逻辑,在 django 中叫做视图(view)。
视图是一个可调用对象,一般为函数。
请求的上下文被打包到一个叫做 HttpRequest 的对象中,并传入视图函数。函数处理后,将结果打包到一个 HttpResponse 对象,并返回给主调方。
这里的主调方,其实就是我们的框架了。
下面是一个比较典型的视图函数:
1 | def welcome(request, nickname): |
这个示例函数的结构比较清晰。需要注意的是,参数里有一个 nickname,django 会把资源地址中的匹配参数一并作为视图参数传递过来。
与该函数绑定的 url 为:
1 | [r'/welcome/(?P<nickname>\w+)', views.welcome] |
可以看到 nickname 的来源及解析方式。
请求上下文
那么请求的上下文是如何构造出来的呢,下面就是构造的过程:
1 | class HttpRequest: |
我们可以看到,HttpRequest 是通过解析一个 environ 字典生成的。environ 字典里包含了请求的上下文信息。至于 environ 从何而来,它实际上是 wsgi 接口定义。我们在下篇文章展开。
environ 里包含了所有请求相关的信息,上例中的 path_info 实际上就是我们的请求地址了,比如前面的 '/welcome/oog'
。
HttpResponse 也会解析请求参数及 COOKIE 等,这样我们就可以很方便的获取需要的信息了。
http 响应
请求被处理完后,视图函数需要返回一个 HttpResponse 对象。该对象包含了需要返回的信息。
一个 http 请求返回的结果,比较典型的有下面几项:
- status code,它定义了请求被处理的结论,比如 200 表示成功,302 表示该资源需要跳转到其它资源地址等
- body,比如一段 html 代码,或者是一个故事的文本描述
- content type,标识 body 的类型,以方便资源请求方正确理解它。比如 text/html、text/plain 等类型
HttpResponse类的定义如下:
1 | class HttpResponse: |
请求、响应流程
现在我们已经有请求解析和响应对象的构造,一个请求过来是如何发生的呢?
我们先来看 8 行代码:
1 | def wsgi_application(environ, start_response): |
代码中,得到 request 后,调用函数并获取 response,然后把关键信息按需要的格式返回即可。
其中 handle_view() 是一个 10 行函数,功能是根据 url 找到视图函数并执行。具体参见 jango 的源码 https://github.com/pysnow530/jango。
这里的结果渲染部分初看会有点奇怪,这里其实是 wsgi 定义的规范,后面的文章会讲到。
到这里,我们就已经完成了一个 url 从请求匹配,到视图执行,最后到请求响应的完整过程。文章里讲到的 wsgi 将会在下一篇文章细说。
一些重要细节
我们上面看到的视图,都是一些函数的形式。如果看 django 的官方文档,会发现 django 也提供了一种类的方式,类名对应请求名。
1 | class Welcome(View): |
但是不要被外在形式迷惑,类形式的视图本质也是一个可调用对象,只是通过 Welcome.as_view() 包装的语法糖方便使用。具体可参考 django 源码。
另外一点,http 比例子中讲到的功能要更为丰富,它还涉及了文件的上传下载等功能。具体可参考扩展资源给出的 rfc 文档。
扩展资料
http 协议可参考 https://tools.ietf.org/html/rfc2616。