Пытаюсь понять интерфейс WSGI в Django - PullRequest
0 голосов
/ 04 мая 2020

Недавно я пытался понять, что такое приложение 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() не передается с environ или start_response функция

Так как это понять

1 Ответ

1 голос
/ 04 мая 2020

Вы не можете видеть, что передается application - это работа контейнера WSGI, а не ваша. Вы должны определить application как нечто, что может быть передано этим двум аргументам.

Существуют различные способы сделать вызываемый. Простейшей является функция:

def add5(x):
    return x + 5

Другая - анонимная функция, или лямбда:

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):
        # ...

Вы можете заметить, что он выглядит почти так же, как мой последний пример: функция, которая создает вызываемый объект. Вызываемый объект может быть вызван с двумя параметрами: environ и start_response.

На стороне вызова, которая не в вашем коде, но в контейнере WSGI (например, Apache mod_wsgi, или в gUnicorn ...), будет выглядеть так, используете ли вы простую функцию (как в первом примере) или вызываемый объект (как в Django):

response = application(environ, start_response)
...