尝试理解Django中的WSGI接口



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

WSGI应用程序只是一个可调用的对象,它被传递给环境-一个包含请求数据的dict,以及一个被调用以开始发送响应的start_response函数。

为了将数据发送到服务器,您所要做的就是调用start_response并返回一个可迭代的。

因此,这里有一个简单的应用程序:

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

还有一个是具有__call__方法的类的对象:

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

您可以将其中任何一个封装到一个函数中,该函数返回一个可调用的:

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 AdderOfY:
def __init__(self, y):
self.y = y
def __call__(self, x):
return x + self.y
add5 = AdderOfY(5)

我想我们甚至可以制作一个函数,构造一个可调用的对象并将其返回给我们:

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函数是一个包装器,它返回一个相同形式的可调用函数:一个可以给定环境并启动响应的函数。

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

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)

最新更新