原文地址:http://projectsedu.com/2016/10/17/django从请求到返回都经历了什么/

从runserver说起
  1. ruserver是使用django自己的web server,主要用于开发和调试中, 部署到线上环境一般使用nginx+uwsgi模式
manage.py 探秘
  1. 看一下manager.py的源码,你会发现上面的命令其实是通过Djangoexecute_from_command_line方法执行了内部实现的runserver命令,那么现在看一下runserver具体做了什么。。
  2. 通过源码分析可知, ruserserver主要完成两件事:
  3. 1). 解析参数,并通过django.core.servers.basehttp.get_internal_wsgi_application方法获取wsgi handler;
  4. 2). 根据ip_addressport生成一个WSGIServer对象,接受用户请求

get_internal_wsgi_application的源码如下:

  1. 通过上面的代码我们可以知道,Django会先根据settings中的WSGI_APPLICATION来获取handler
  2. 在创建project的时候,Django会默认创建一个wsgi.py文件,而settings中的WSGI_APPLICATION配置也会默认指向这个文件。看一下这个wsgi.py文件,其实它也和上面的逻辑一样,最终调用get_wsgi_application实现。
django http请求处理流程
  1. Django和其他Web框架一样,HTTP的处理流程基本类似:接受request,返回response内容。Django的具体处理流程大致如下:
1. 加载settings.py
  1. 在通过django-admin.py创建project的时候,Django会自动生成默认的settings文件和manager.py等文件,在创建WSGIServer之前会执行下面的引用:
  2. from django.conf import settings
  3. 上面引用在执行时,会读取os.environ中的DJANGO_SETTINGS_MODULE配置,加载项目配置文件,生成settings对象。所以,在manager.py文件中你可以看到,在获取WSGIServer之前,会先将projectsettings路径加到os路径中。
2. 创建WSGIServer
  1. 不管是使用runserver还是uWSGI运行Django项目,在启动时都会调用django.core.servers.basehttp中的run()方法
  2. 创建一个django.core.servers.basehttp.WSGIServer类的实例,之后调用其serve_forever()方法启动HTTP服务。run方法的源码如下:
  3. def run(addr, port, wsgi_handler, ipv6=False, threading=False):
  4. server_address = (addr, port)
  5. if threading:
  6. httpd_cls = type(str('WSGIServer'), (socketserver.ThreadingMixIn, WSGIServer), {})
  7. else:
  8. httpd_cls = WSGIServer
  9. httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
  10. if threading:
  11. # ThreadingMixIn.daemon_threads indicates how threads will behave on an
  12. # abrupt shutdown; like quitting the server by the user or restarting
  13. # by the auto-reloader. True means the server will not wait for thread
  14. # termination before it quits. This will make auto-reloader faster
  15. # and will prevent the need to kill the server manually if a thread
  16. # isn't terminating correctly.
  17. httpd.daemon_threads = True
  18. httpd.set_app(wsgi_handler)
  19. httpd.serve_forever()
  20. 如上,我们可以看到:在创建WSGIServer实例的时候会指定HTTP请求的Handler
  21. 上述代码使用WSGIRequestHandler。当用户的HTTP请求到达服务器时,
  22. WSGIServer会创建WSGIRequestHandler实例,使用其handler方法来处理HTTP请求(其实最终是调用wsgiref.handlers.BaseHandler中的run方法处理)。
  23. WSGIServer通过set_app方法设置一个可调用(callable)的对象作为application,上面提到的handler方法最终会调用设置的application处理request,并返回response
  24. 其中,WSGIServer继承自wsgiref.simple_server.WSGIServer,而WSGIRequestHandler继承自wsgiref.simple_server.WSGIRequestHandlerwsgirefPython标准库给出的WSGI的参考实现。其源码可自行到wsgiref参看,这里不再细说。
3. 处理Request
  1. 第二步中说到的application,在Django中一般是django.core.handlers.wsgi.WSGIHandler对象,WSGIHandler继承自django.core.handlers.base.BaseHandler,这个是Django处理request的核心逻辑,它会创建一个WSGIRequest实例,而WSGIRequest是从http.HttpRequest继承而来
4. 返回Response
  1. 上面提到的BaseHandler中有个get_response方法,该方法会先加载Django项目的ROOT_URLCONF,然后根据url规则找到对应的view方法(类),view逻辑会根据request实例生成并返回具体的response
  2. Django返回结果之后,第二步中提到wsgiref.handlers.BaseHandler.run方法会调用finish_response结束请求,并将内容返回给用户
Django处理Request的详细流程
  1. 首先给大家分享两个网上看到的Django流程图:


流程图一


流程图二

上面的两张流程图可以大致描述Django处理request的流程,按照流程图2的标注,可以分为以下几个步骤:

  1. 1. 用户通过浏览器请求一个页面
  2. 2.请求到达Request Middlewares,中间件对request做一些预处理或者直接response请求
  3. 3.URLConf通过urls.py文件和请求的URL找到相应的View
  4. 4.View Middlewares被访问,它同样可以对request做一些处理或者直接返回response
  5. 5.调用View中的函数
  6. 6.View中的方法可以选择性的通过Models访问底层的数据
  7. 7.所有的Model-to-DB的交互都是通过manager完成的
  8. 8.如果需要,Views可以使用一个特殊的Context
  9. 9.Context被传给Template用来生成页面
  10. a.Template使用FiltersTags去渲染输出
  11. b.输出被返回到View
  12. c.HTTPResponse被发送到Response Middlewares
  13. d.任何Response Middlewares都可以丰富response或者返回一个完全不同的response
  14. e.Response返回到浏览器,呈现给用户
  15. 上述流程中最主要的几个部分分别是:Middleware(中间件,包括request, view, exception, response),URLConf(url映射关系),Template(模板系统),下面一一介绍一下。
1. Middleware(中间件)
  1. Middleware并不是Django所独有的东西,在其他的Web框架中也有这种概念。在Django中,Middleware可以渗入处理流程的四个阶段:requestviewresponseexception,相应的,在每个Middleware类中都有rocess_requestprocess_view process_response process_exception这四个方法。你可以定义其中任意一个活多个方法,这取决于你希望该Middleware作用于哪个处理阶段。每个方法都可以直接返回response对象。
  2. Middleware是在Django BaseHandlerload_middleware方法执行时加载的,加载之后会建立四个列表作为处理器的实例变量:
  3. _request_middlewareprocess_request方法的列表
  4. _view_middlewareprocess_view方法的列表
  5. _response_middlewareprocess_response方法的列表
  6. _exception_middlewareprocess_exception方法的列表
  7. Django的中间件是在其配置文件(settings.py)的MIDDLEWARE_CLASSES元组中定义的。在MIDDLEWARE_CLASSES中,中间件组件用字符串表示:指向中间件类名的完整Python路径。例如
  8. `MIDDLEWARE_CLASSES = [
  9. 'django.middleware.security.SecurityMiddleware',
  10. 'django.contrib.sessions.middleware.SessionMiddleware',
  11. 'django.middleware.common.CommonMiddleware',
  12. 'django.middleware.csrf.CsrfViewMiddleware',
  13. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  14. 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
  15. 'django.contrib.messages.middleware.MessageMiddleware',
  16. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  17. ]`
  18. Django项目的安装并不强制要求任何中间件,如果你愿意,MIDDLEWARE_CLASSES可以为空。中间件出现的顺序非常重要:在requestview的处理阶段,Django按照MIDDLEWARE_CLASSES中出现的顺序来应用中间件,而在responseexception异常处理阶段,Django则按逆序来调用它们。也就是说,DjangoMIDDLEWARE_CLASSES视为view函数外层的顺序包装子:在request阶段按顺序从上到下穿过,而在response则反过来。以下这张图可以更好地帮助你理解:

  1. URLConf(URL映射)
  1. 如果处理request的中间件都没有直接返回response,那么Django会去解析用户请求的URLURLconf就是Django所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表。通过这种方式可以告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。具体的,在Django项目的配置文件中有ROOT_URLCONF常量,这个常量加上根目录"/",作为参数来创建django.core.urlresolvers.RegexURLResolver的实例,然后通过它的resolve方法解析用户请求的URL,找到第一个匹配的view
  2. 有关urlconf的内容,大家可以参考 [理解curlConf]()
  1. Template(模板)
  1. 大部分web框架都有自己的Template(模板)系统,Django也是。但是,Django模板不同于Mako模板和jinja2模板,在Django模板不能直接写Python代码,只能通过额外的定义filtertemplate tag实现。由于本文主要介绍Django流程,模板内容就不过多介绍。

最后欢迎大家观看我关于 django + xadmin的教程:

  1. http://coding.imooc.com/class/evaluation/78.html

 

 
 

django从请求到返回都经历了什么[转]的更多相关文章

  1. Django从请求到返回流程

    图1:流程图 1. 用户通过浏览器请求一个页面2.请求到达Request Middlewares,中间件对request做一些预处理或者直接response请求3.URLConf通过urls.py文件 ...

  2. Python的Django REST框架中的序列化及请求和返回

    Python的Django REST框架中的序列化及请求和返回 序列化Serialization 1. 设置一个新的环境 在我们开始之前, 我们首先使用virtualenv要创建一个新的虚拟环境,以使 ...

  3. MOOC(2)-Django开发get、post请求,返回json数据

    1.对get请求直接返回参数 如果请求多个参数,也只能返回一个参数,这里只返回了username参数 如果想要返回多个参数值,可以返回json格式数据 2.对get请求返回json数据 # views ...

  4. django HTTP请求(Request)和回应(Response)对象

    Django使用request和response对象在系统间传递状态.—(阿伦)当一个页面被请示时,Django创建一个包含请求元数据的 HttpRequest 对象. 然后Django调入合适的视图 ...

  5. Django中请求的生命周期

    1. 概述 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串. 在Django中,当我们访问一个的url时,会通过路由匹配进入相应的html网页中. Django的请求生命周期是指当用户 ...

  6. 一个页面从输入url到页面加载显示完成,中间都经历了什么

    第一种解释: 一般会经历以下几个过程: 1.首先,在浏览器地址栏中输入url 2.浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容.若没有,则跳到第三步操作. 3 ...

  7. 访问了一次百度网页,你都经历了什么?https及tcp协议揭秘

    打开https://www.baidu.com/ 网页一个简单的动作,都经历了什么?你想探究内部的原理吗?那我们一起去探索吧 1.准备工作 安装好wireshark.Wireshark(前称Ether ...

  8. Django的请求生命周期

    Django的请求生命周期 请求生命周期 请求生命周期是指当用户在浏览器上输入url到用户看到网页的这个时间段内,Django后台所发生的事情. 1.客户端发送Http请求 2 .服务器接收,根据请求 ...

  9. Django 框架 django的请求生命周期

    概述 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串,同时http请求是无状态的,可以通过session和cookie来辅助. 浏览器通过ip和端口及路由方式访问服务端. 在Djang ...

随机推荐

  1. The Ultimate Guide To A/B Testing

    w http://blog.jobbole.com/25576/?utm_source=blog.jobbole.com&utm_medium=relatedPosts https://www ...

  2. Tornado实战

    抽屉之Tornado实战(1)--分析与架构 抽屉之Tornado实战(2)--数据库表设计 抽屉之Tornado实战(3)--注册 抽屉之Tornado实战(4)--发帖及上传图片 抽屉之Torna ...

  3. Web页面性能优化(YSlow)

    YSlow(解析为Why Slow)是雅虎基于网站优化规则推出的工具,帮助你分析并优化网站性能.旧版Yslow 有13条规则,新版Yslow有23项规则,YSlow会根据这些规则分析你的网站,并给出评 ...

  4. struts2的HelloWorld的基本过程

    login.jsp中 <form action="Login"... 该页面提交后, web.xml中设置的过滤器会起作用     <filter>        ...

  5. redis的数据类型与应用场景(二)

    1. 如何学习 redis有好多数据类型,有这么多数据类型,我们不可能每个都记得完完全全.但是我们必须知道它有哪些数据类型,每个数据类型是怎样的,有什么作用.redis的每一个数据类型都有一大堆命令, ...

  6. Cpython-并发编程

    阅读目录 一 背景知识 二 python并发编程之多进程 三 python并发编程之多线程 四 python并发编程之协程 五 python并发编程之IO模型 六 补充:paramiko模块 七 作业 ...

  7. Kattis - pizzahawaii 【状态标记】

    Kattis - pizzahawaii [状态标记] Description You are travelling in a foreign country. Although you are al ...

  8. Codeforces Round #396 (Div. 2) C. Mahmoud and a Message

    地址:http://codeforces.com/contest/766/problem/C 题目: C. Mahmoud and a Message time limit per test 2 se ...

  9. json数据结构

    JSON即JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合服务器与JavaScript的交互.JSON易于人阅读和编写.同时也易于机器解析和生成.JSON采 ...

  10. Connection.setAutoCommit使用的注意事项

    http://blog.csdn.net/xiayimiaokuaile/article/details/6422032 setAutoCommit总的来说就是保持数据的完整性,一个系统的更新操作可能 ...