Spec-Zone.ru › Flask 1.0

Развёртывание приложений

Развёртывание приложения — это процесс объединения нескольких приложений Flask на уровне WSGI. Вы можете объединить не только приложения Flask, но и любые WSGI-приложения. Это позволит вам запустить приложение Django и приложение Flask в одном интерпретаторе бок о бок, если вам это нужно. Полезность этого зависит от того, как приложения работают внутри.

Основное отличие от подхода с модулями заключается в том, что в данном случае вы запускаете те же или разные приложения Flask, которые полностью изолированы друг от друга. Они используют разные конфигурации и обрабатываются на уровне WSGI.

Работа с этим документом

Каждый из приведённых ниже методов и примеров приводит к объекту application, который можно запустить с любым WSGI-сервером. Для производства см. Варианты развертывания. Для разработки Werkzeug предоставляет встроенный сервер для разработки, доступный по адресу werkzeug.serving.run_simple():

from werkzeug.serving import run_simple
run_simple('localhost', 5000, application, use_reloader=True)

Обратите внимание, что run_simple не предназначен для использования в производственной среде. Используйте полноценный WSGI-сервер.

Для использования интерактивного отладчика отладка должна быть включена как в приложении, так и в простом сервере. Вот пример «hello world» с отладкой и run_simple:

from flask import Flask
from werkzeug.serving import run_simple

app = Flask(__name__)
app.debug = True

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    run_simple('localhost', 5000, app,
               use_reloader=True, use_debugger=True, use_evalex=True)

Объединение приложений

Если у вас есть полностью отделённые приложения, и вы хотите, чтобы они работали рядом друг с другом в одном процессе интерпретатора Python, вы можете воспользоваться werkzeug.wsgi.DispatcherMiddleware. Идея в том, что каждое приложение Flask является допустимым WSGI-приложением, и они объединяются посредством посредника-диспетчера в более крупное приложение, которое обрабатывается на основе префикса.

Например, вы можете запустить своё основное приложение по / и интерфейс вашего бэкенда по /backend:

from werkzeug.middleware.dispatcher import DispatcherMiddleware
from frontend_app import application as frontend
from backend_app import application as backend

application = DispatcherMiddleware(frontend, {
    '/backend': backend
})

Обработка по домену верхнего уровня

Иногда вам может понадобиться использовать несколько экземпляров одного приложения с разными конфигурациями. Если приложение создаётся внутри функции, и вы можете вызвать эту функцию для его создания, это очень легко реализовать. Чтобы разработать ваше приложение для поддержки создания новых экземпляров в функциях, ознакомьтесь с шаблоном Фабрики приложений.

Очень распространённым примером является создание приложений для каждого поддомена. Например, вы настраиваете свой веб-сервер для перенаправления всех запросов со всех поддоменов вашему приложению, а затем используете информацию о поддомене для создания пользовательских экземпляров. После настройки сервера для прослушивания всех поддоменов вы можете использовать очень простое WSGI-приложение для динамического создания приложений.

Идеальный уровень абстракции в этом случае — уровень WSGI. Вы пишете собственное WSGI-приложение, которое анализирует входящий запрос и перенаправляет его вашему приложению Flask. Если такое приложение ещё не существует, оно динамически создаётся и запоминается:

from threading import Lock

class SubdomainDispatcher(object):

    def __init__(self, domain, create_app):
        self.domain = domain
        self.create_app = create_app
        self.lock = Lock()
        self.instances = {}

    def get_application(self, host):
        host = host.split(':')[0]
        assert host.endswith(self.domain), 'Configuration error'
        subdomain = host[:-len(self.domain)].rstrip('.')
        with self.lock:
            app = self.instances.get(subdomain)
            if app is None:
                app = self.create_app(subdomain)
                self.instances[subdomain] = app
            return app

    def __call__(self, environ, start_response):
        app = self.get_application(environ['HTTP_HOST'])
        return app(environ, start_response)

Этот диспетчер можно использовать следующим образом:

from myapplication import create_app, get_user_for_subdomain
from werkzeug.exceptions import NotFound

def make_app(subdomain):
    user = get_user_for_subdomain(subdomain)
    if user is None:
        # if there is no user for that subdomain we still have
        # to return a WSGI application that handles that request.
        # We can then just return the NotFound() exception as
        # application which will render a default 404 page.
        # You might also redirect the user to the main page then
        return NotFound()

    # otherwise create the application for the specific user
    return create_app(user)

application = SubdomainDispatcher('example.com', make_app)

Обработка по пути

Обработка по пути в URL очень похожа. Вместо того, чтобы анализировать заголовок Host для определения поддомена, просто анализируется путь запроса до первого слэша:

from threading import Lock
from werkzeug.wsgi import pop_path_info, peek_path_info

class PathDispatcher(object):

    def __init__(self, default_app, create_app):
        self.default_app = default_app
        self.create_app = create_app
        self.lock = Lock()
        self.instances = {}

    def get_application(self, prefix):
        with self.lock:
            app = self.instances.get(prefix)
            if app is None:
                app = self.create_app(prefix)
                if app is not None:
                    self.instances[prefix] = app
            return app

    def __call__(self, environ, start_response):
        app = self.get_application(peek_path_info(environ))
        if app is not None:
            pop_path_info(environ)
        else:
            app = self.default_app
        return app(environ, start_response)

Главное отличие от обработки по поддомену заключается в том, что в данном случае происходит возврат к другому приложению, если функция-создатель возвращает None:

from myapplication import create_app, default_app, get_user_for_prefix

def make_app(prefix):
    user = get_user_for_prefix(prefix)
    if user is not None:
        return create_app(user)

application = PathDispatcher(default_app, make_app)

© 2007–2020 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/1.0.x/patterns/appdispatch/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API