试图理解 Django 中的 WSGI 接口

Tyring to understand WSGI interface in Django

我最近试图了解什么是 WSGI 应用程序:

a WSGI application is just a callable object that is passed an environ - a dict that contains request data, and a start_response function that is called to start sending the response.

In order to send data to the server all you have to do is to call start_response and return an iterable.

So, here's a simple application:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return ['Hello World!']

Djangos wsgi.py 是

"""
WSGI config for basic_django project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
"""
import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'basic_django.settings')

application = get_wsgi_application()

但是当我看到 wsgi.py 时,application = get_wsgi_application() 可调用函数没有通过 environstart_response 函数传递

那么如何理解这个

您看不到传递给 application 的内容 - 那是 WSGI 容器的工作,不是您的。你的任务是定义application作为可以通过这两个论点的东西。

有多种方法可以调用。最简单的是一个函数:

def add5(x):
    return x + 5

另一个是匿名函数,或者lambda:

add5 = lambda x: x + 5

还有一个是 class 的对象,它有 __call__ 方法:

class AdderOf5:
    def __call__(self, x):
        return x + 5

add5 = AdderOf5()

并且您可以将其中任何一个包装到 return 可调用的函数中:

def make_add_y(y):
    def add_y(x):
        return x + y
    return add_y
add5 = make_add_y(5)

def make_add_y(y):
    return lambda x: x + y
add5 = make_add_y(5)

第三个选项并不完全需要包装器,因为 class 已经是一个工厂:

class AdderOfY:
    def __init__(self, y):
        self.y = y

    def __call__(self, x):
        return x + self.y

add5 = AdderOfY(5)

而且我想我们甚至可以创建一个函数来构造一个可调用对象,然后 return 它给我们:

class AdderOfY:
    def __init__(self, y):
        self.y = y

    def __call__(self, x):
        return x + self.y

def make_adder(y):
    return AdderOfY(5)

add5 = make_adder(5)

所有这些都展示了如何定义 一个可调用对象。可调用对象的调用方式是一段不同的代码,无论可调用对象的定义方式如何,它看起来都一样:

eight = add5(3)

您可以尝试验证此行是否有效,无论我们采用哪种方式构建 add5


返回 WSGI:您提供的示例创建了一个接受两个参数的简单函数。

Django 的 get_wsgi_application 函数是一个包装器,return 是一个相同形式的可调用函数:一个可以给定环境并开始响应的函数。

如果你想看看它是如何定义的,下面是它的样子:

get_wsgi_application:

def get_wsgi_application():
    # ...
    return WSGIHandler()

WSGIHandler:

class WSGIHandler(base.BaseHandler):
    # ...
    def __call__(self, environ, start_response):
        # ...

您会注意到它看起来与我上一个示例几乎完全相同:一个构造可调用对象的函数。可以使用两个参数调用可调用对象:environstart_response.

在调用端,在您的代码中 不是 ,而是在 WSGI 容器中(例如 Apache 的 mod_wsgi,或在 gUnicorn...),它看起来像这样,无论您使用的是简单函数(如第一个示例)还是可调用对象(如 Django):

response = application(environ, start_response)