Spec-Zone.ru › Flask 2.3

Загрузка представлений с отложенной инициализацией

Flask обычно используется с декораторами. Декораторы просты, и у вас есть URL непосредственно рядом с функцией, которая вызывается для этого конкретного URL. Однако у этого подхода есть недостаток: это означает, что весь ваш код, использующий декораторы, должен быть импортирован заранее, иначе Flask никогда не найдёт вашу функцию.

Это может быть проблемой, если ваше приложение должно импортировать быстро. Это может потребоваться в системах, таких как Google App Engine, или других системах. Поэтому, если вы внезапно заметите, что ваше приложение перерастает этот подход, вы можете вернуться к централизованному отображению 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–2022 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.3.x/patterns/lazyloading/

Spec-Zone.ru

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