[TimLinux] django WSGI入口分析及自定义WSGIHandler思路

1. 命令行启动

命令行是通过runserver子命令来启动的,对应的django模块为django.core.management.commands.runserver,调用关系结构:

# 简化的运行代码:
django.core.management.commands.runserver.py

class Command:
    def get_handler():
        return django.core.servers.basehttp.get_internal_wsgi_application()

    def run:  # 命令行如果函数
        self.run_inner()

    def run_inner():
        handler = self.get_handler()
        django.core.servers.basehttp.run(..., handler, ...)


django.core.servers.basehttp.py
def get_internal_wsgi_application():
    1. settings.WSGI_APPLICAITON
    2. 上面的配置不存在,则执行:
        django.core.wsgi.get_wsgi_application()

def run():
    启动http服务,监听端口,注册WSGI


django.core.wsgi.py
def get_wsgi_application():
    django.setup()
    return django.core.handlers.wsgi.WSGIHandler()


django.core.handlers.wsgi.py
class WSGIHandler(base.BaseHandler):
    def __init__():
        self.load_middleware()  # 装载了中间件

    def __call__(self, environ, start_response):  # 请求的入口函数
        pass

2. web服务器启动

Web服务器配置:
WSGIScriptAlias / /my/web/site/site/wsgi.py

site/wsgi.py # 这个文件默认是与settings.py同级
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE", 'site.settings')
application = get_wsgi_applicaiton()


application变量的获取与命令行最后部分是一致的。

3. 核心

这个核心函数的处理内容:
django.core.wsgi.WSGIHandler.__call__(self, environ, start_response)
1. 发送一个信号
2. 处理请求、处理中间件
3. 处理响应
4. 调用start_response返回响应头
5. 返回响应体

__call__ 函数的特点:
1. 每次请求的入口函数
2. 这个函数内部代码都属于请求过程,也就是线程工作空间

4. 自定义 WSGI 思路

关键在于自定义 get_wsgi_applicaiton函数:
1. 根据代码,我认为可以在 settings 中配置 WSGI_APPLICATION 的方式来定义该函数,这个可能只能解决命令行启动问题
2. web服务器启动的时候,因为 site/wsgi.py 文件属于站点独立文件,我们其实可以自己重新这个文件的,这样很容易调用到自己定义的 get_wsgi_application() 函数
3. get_wsgi_applicaiton() 函数的返回值 设置为自己实现的 WSGIHandler() 就可以实现自己的 WSGI了。
4. 在 WSGIHandler 的 __call__ 方法内,定义一些全局变量,这个变量将属于整个线程,并且可以在各关联函数内使用,比如给
signals增加一个request 属性,则可以在所有 signal receiver函数内访问到这个属性了。
def __call__(...): setattr(signals, 'request', request)

 5. 另外一种方法

这个方法的关键在于提供一个 middleware,然后在 middleware 的process_request 方法内,给一个公共模块设置属性的值,
这样这个属性的值在各模块内都是可访问的。
class MyMiddleware(MiddlewareMixin): def process_request(self, request): setattr(signals, 'request', request) def my(sender, **kwargs): if hasattr(signals, 'request'): print(singals.request) request_started.connect(my, sender=WSGIRequest)

猜你喜欢

转载自www.cnblogs.com/timlinux/p/9354716.html
今日推荐