Загрузка представлений с отложенной инициализацией
Flask обычно используется с декораторами. Декораторы просты, и у вас есть URL прямо рядом с функцией, которая вызывается для этого конкретного URL. Однако у этого подхода есть недостаток: это означает, что весь ваш код, использующий декораторы, должен быть импортирован заранее, иначе Flask никогда не найдет вашу функцию.
Это может быть проблемой, если вашему приложению нужно импортировать быстро. Возможно, это нужно будет сделать на системах, таких как App Engine от Google, или на других системах. Поэтому, если вы вдруг заметите, что ваше приложение выходит за рамки этого подхода, вы можете вернуться к централизованному отображению URL.
Система, которая позволяет иметь централизованную карту URL, — это функция add_url_rule(). Вместо использования декораторов у вас есть файл, который настраивает приложение со всеми URL.
Преобразование в централизованную карту URL
Представьте, что текущее приложение выглядит примерно так:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
pass
@app.route('/user/<username>')
def user(username):
pass
Затем, с централизованным подходом у вас будет один файл с представлениями (views.py) но без каких-либо декораторов:
def index():
pass
def user(username):
pass
И затем файл, который настраивает приложение, сопоставляя функции с URL:
from flask import Flask
from yourapplication import views
app = Flask(__name__)
app.add_url_rule('/', view_func=views.index)
app.add_url_rule('/user/<username>', view_func=views.user)
Загрузка с отложенной инициализацией
До сих пор мы только разделили представления и маршрутизацию, но модуль по-прежнему загружается заранее. Хитрость заключается в том, чтобы фактически загружать функцию представления по мере необходимости. Это можно сделать с помощью вспомогательного класса, который ведет себя как функция, но внутри импортирует реальную функцию при первом использовании:
from werkzeug.utils import import_string, cached_property
class LazyView(object):
def __init__(self, import_name):
self.__module__, self.__name__ = import_name.rsplit('.', 1)
self.import_name = import_name
@cached_property
def view(self):
return import_string(self.import_name)
def __call__(self, *args, **kwargs):
return self.view(*args, **kwargs)
Важно, чтобы __module__ и __name__ были правильно заданы. Это используется Flask внутри для определения того, как назвать правила URL, если вы сами не предоставите имя для правила.
Затем вы можете определить центральное место для объединения представлений следующим образом:
from flask import Flask
from yourapplication.helpers import LazyView
app = Flask(__name__)
app.add_url_rule('/',
view_func=LazyView('yourapplication.views.index'))
app.add_url_rule('/user/<username>',
view_func=LazyView('yourapplication.views.user'))
Вы можете дополнительно оптимизировать это с точки зрения количества необходимых нажатий клавиш, написав функцию, которая вызывает add_url_rule(), добавляя к строке имя проекта и точку, и обернув view_func в LazyView по мере необходимости.
def url(import_name, url_rules=[], **options):
view = LazyView(f"yourapplication.{import_name}")
for url_rule in url_rules:
app.add_url_rule(url_rule, view_func=view, **options)
# add a single route to the index view
url('views.index', ['/'])
# add two routes to a single function endpoint
url_rules = ['/user/','/user/<username>']
url('views.user', url_rules)
Следует помнить, что обработчики запросов до и после запроса должны находиться в файле, который импортируется заранее, чтобы работать должным образом при первом запросе. То же самое относится к любому оставшемуся декоратору.
© 2007–2021 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.0.x/patterns/lazyloading/