Выдача приложений
Выдача приложений — это процесс объединения нескольких приложений Flask на уровне WSGI. Вы можете объединить не только приложения Flask, но и любые WSGI-приложения. Это позволит вам запустить Django и приложение Flask в одном и том же интерпретаторе бок о бок, если вам нужно. Полезность этого зависит от того, как приложения работают внутри.
Основное отличие от Крупные приложения как пакеты заключается в том, что в этом случае вы запускаете одни и те же или разные приложения Flask, которые полностью изолированы друг от друга. Они используют разные конфигурации и выдаются на уровне WSGI.
Работа с этим документом
Каждый из приведенных ниже методов и примеров приводит к объекту application, который можно запустить с любым WSGI-сервером. Для разработки используйте команду flask run для запуска сервера разработки. Для производства см. Развертывание в производство.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
Объединение приложений
Если у вас есть полностью отдельные приложения, и вы хотите, чтобы они работали рядом друг с другом в одном процессе интерпретатора Python, вы можете воспользоваться werkzeug.wsgi.DispatcherMiddleware. Идея здесь в том, что каждое приложение Flask является допустимым WSGI-приложением, и они объединяются посредством middleware-диспетчера в более крупное, которое выдается на основе префикса.
Например, вы можете запустить основное приложение на / и интерфейс заднего плана на /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:
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 wsgiref.util import shift_path_info
class PathDispatcher:
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:
shift_path_info(environ)
else:
app = self.default_app
return app(environ, start_response)
def _peek_path_info(environ):
segments = environ.get("PATH_INFO", "").lstrip("/").split("/", 1)
if segments:
return segments[0]
return None
Основное отличие от варианта с доменными именами состоит в том, что в этом случае происходит обращение к другому приложению, если функция-создатель возвращает 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)
© 2010 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/3.0.x/patterns/appdispatch/