乍见

Django内置的server基本包括两部分:django.core.servers和django.core.handlers

相识

servers.basehttp是Django自身提供的一个用于开发测试的server模块,其中提供的WSGIServer、ServerHandler、WSGIRequestHandler其实都是属于WSGI server,django只不过是对python内置的WSGI模块simple_server做的一层包装。

handlers package包括base.py和wsgi.py两个模块。
base.py中只定义了一个BaseHandler类,它复杂一些基础的功能,比如加载中间件,处理异常,获取响应数据等

wsgi.py才是主角,其中最重要的就是WSGIHandler类,它继承了base.py中的BaseHandler,只添加了一个__call__方法,那为什么添加这个方法呢?

django.core.wsgi

  1. import django
  2. from django.core.handlers.wsgi import WSGIHandler
  3. def get_wsgi_application():
  4. """
  5. The public interface to Django's WSGI support. Should return a WSGI
  6. callable.
  7. Allows us to avoid making django.core.handlers.WSGIHandler public API, in
  8. case the internal WSGI implementation changes or moves in the future.
  9. """
  10. django.setup()
  11. return WSGIHandler()

可见我们启动server时传入的application其实是WSGIHandler的一个实例,而根据WSGI规范,这个application必须要是callable,python中的callable包括函数、方法以及任何定义了__call__方法的对象

回到handlers.wsgi

  1. class WSGIHandler(base.BaseHandler):
  2. initLock = Lock()
  3. request_class = WSGIRequest
  4. def __call__(self, environ, start_response):
  5. # Set up middleware if needed. We couldn't do this earlier, because
  6. # settings weren't available.
  7. if self._request_middleware is None:
  8. with self.initLock:
  9. try:
  10. # Check that middleware is still uninitialized.
  11. if self._request_middleware is None:
  12. self.load_middleware()
  13. except:
  14. # Unload whatever middleware we got
  15. self._request_middleware = None
  16. raise
  17. set_script_prefix(get_script_name(environ))
  18. signals.request_started.send(sender=self.__class__, environ=environ)
  19. try:
  20. request = self.request_class(environ)
  21. except UnicodeDecodeError:
  22. logger.warning('Bad Request (UnicodeDecodeError)',
  23. exc_info=sys.exc_info(),
  24. extra={
  25. 'status_code': 400,
  26. }
  27. )
  28. response = http.HttpResponseBadRequest()
  29. else:
  30. response = self.get_response(request)
  31. response._handler_class = self.__class__
  32. status = '%s %s' % (response.status_code, response.reason_phrase)
  33. response_headers = [(str(k), str(v)) for k, v in response.items()]
  34. for c in response.cookies.values():
  35. response_headers.append((str('Set-Cookie'), str(c.output(header=''))))
  36. start_response(force_str(status), response_headers)
  37. if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
  38. response = environ['wsgi.file_wrapper'](response.file_to_stream)
  39. return response

由于__call__是一个请求的入口,它需要调用BaseHandler中定义的方法去执行加载中间件等一系列操作和异常处理,除此之外,WSGIHandler还会处理cookie、触发signal等。

至于如何返回响应,具体可看handlers.base模块,大概就是找出请求的path,通过匹配路由,找到并执行用户定义的view方法,执行中间件处理方法,最后返回响应。当然,还有一系列的异常处理。

回想

这部分的内容需要对WSGi协议有个大致的了解,可以参考:http://xiaorui.cc/2016/04/16/%E6%89%93%E9%80%A0mvc%E6%A1%86%E6%9E%B6%E4%B9%8Bwsgi%E5%8D%8F%E8%AE%AE%E7%9A%84%E4%BC%98%E7%BC%BA%E7%82%B9%E5%8F%8A%E6%8E%A5%E5%8F%A3%E5%AE%9E%E7%8E%B0/

Django源码分析之server的更多相关文章

  1. django源码分析 python manage.py runserver

    django是一个快速开发web应用的框架, 笔者也在django框架上开发不少web应用,闲来无事,就想探究一下django底层到底是如何实现的,本文记录了笔者对django源码的分析过程 I be ...

  2. Django源码分析之启动wsgi发生的事

    前言 ​ 好多人对技术的理解都停留在懂得使用即可,因而只会用而不会灵活用,俗话说好奇害死猫,不然我也不会在凌晨1.48的时候决定写这篇博客,好吧不啰嗦了 ​ 继续上一篇文章,后我有个问题(上文:&qu ...

  3. django源码分析——本地runserver分析

    本文环境python3.5.2,django1.10.x系列 1.根据上一篇文章分析了,django-admin startproject与startapp的分析流程后,根据django的官方实例此时 ...

  4. 2、Django源码分析之启动wsgi发生了哪些事

    一 前言 Django是如何通过网络socket层接收数据并将请求转发给Django的urls层? 有的人张口就来:就是通过wsgi(Web Server Gateway Interface)啊! D ...

  5. Apache Kafka源码分析 – Broker Server

    1. Kafka.scala 在Kafka的main入口中startup KafkaServerStartable, 而KafkaServerStartable这是对KafkaServer的封装 1: ...

  6. Kafka源码分析(三) - Server端 - 消息存储

    系列文章目录 https://zhuanlan.zhihu.com/p/367683572 目录 系列文章目录 一. 业务模型 1.1 概念梳理 1.2 文件分析 1.2.1 数据目录 1.2.2 . ...

  7. django源码分析

    原文网址 https://www.jianshu.com/p/17d78b52c732?utm_campaign=maleskine&utm_content=note&utm_medi ...

  8. django源码分析——处理请求到wsgi及视图view

    本文环境python3.5.2,django1.10.x系列 根据前上一篇runserver的博文,已经分析了本地调试服务器的大致流程,现在我们来分析一下当runserver运行起来后,django框 ...

  9. kafka源码分析之一server启动分析

    0. 关键概念 关键概念 Concepts Function Topic 用于划分Message的逻辑概念,一个Topic可以分布在多个Broker上. Partition 是Kafka中横向扩展和一 ...

随机推荐

  1. 11java基础继承

    一.           继承相关   18.实现如下类之间的继承关系,并编写Music类来测试这些类. package com.hry.test; public class Instrument { ...

  2. WebStorm中Node.js项目配置教程——项目设置

    上一章讲解了Node.js项目在WebStorm中的两种创建方式,当完成Node.js项目创建以后,剩下的就是涉及配置设置工作. 为了确保Node.js全局和Node.js核心模块的代码完成功能,打开 ...

  3. pdf.js 在线阅读PDF

    在网上找了一下如何在线显示pdf文件.个人还是觉得这个是比较不错的,这里做一个记录. gitHub:https://github.com/mozilla/pdf.js           这是一个开源 ...

  4. shiro框架 4种授权方式 说明

    1. shiro的配置文件(applicationContext-shiro.xml)中使用filterChain过滤url的方式 详细配置看注释 <?xml version="1.0 ...

  5. 第十四届浙江财经大学程序设计竞赛重现赛--A-A Sad Story

    链接:https://www.nowcoder.com/acm/contest/89/A 来源:牛客网 1.题目描述 The Great Wall story of Meng Jiangnv’s Bi ...

  6. 构建高可靠hadoop集群之4-保全模式

    本文主要翻译自http://hadoop.apache.org/docs/r2.8.0/hadoop-project-dist/hadoop-common/SecureMode.html 译注:之所以 ...

  7. 03 mysql补充 (进阶)

    增加字段 alter table tb1 add age int first; 增加到第一 alter table tb1 add sex int after id; # 改变位置,id是字段名字 a ...

  8. (转)Updates were rejected because the tip of your current branch is behind

    刚创建的github版本库,在push代码时出错: $ git push -u origin masterTo git@github.com:******/Demo.git ! [rejected] ...

  9. python 装饰器 (多个装饰器装饰一个函数---装饰器前套一个函数)

    #带参数的装饰器 #500个函数 # import time # FLAGE = False # def timmer_out(flag): # def timmer(func): # def inn ...

  10. 列表排序之NB三人组附加一个希尔排序

    NB三人组之 快速排序 def partition(li, left, right): tmp = li[left] while left < right: while left < ri ...