Spec-Zone.ru › Flask 1.1

Модульные приложения с Blueprints

Журнал изменений

Новое в версии 0.7.

Flask использует концепцию blueprints для создания компонентов приложения и поддержки общих шаблонов внутри приложения или между приложениями. Blueprints могут значительно упростить работу с крупными приложениями и предоставить централизованный способ для расширений Flask регистрировать операции в приложениях. Объект Blueprint работает аналогично объекту приложения Flask, но фактически не является приложением. Скорее это blueprint (шаблон) того, как построить или расширить приложение.

Зачем использовать Blueprints?

Blueprints в Flask предназначены для следующих случаев:

  • Разбиение приложения на набор blueprints. Это идеально подходит для больших приложений; проект может создать объект приложения, инициализировать несколько расширений и зарегистрировать набор blueprints.
  • Регистрация blueprint на приложении с префиксом URL и/или поддоменом. Параметры в префиксе URL/поддомене становятся общими аргументами представления (с значениями по умолчанию) для всех функций представления в blueprint.
  • Регистрация blueprint несколько раз на приложении с различными правилами URL.
  • Предоставление фильтров шаблонов, статических файлов, шаблонов и других утилит через blueprints. Blueprint не обязательно должен реализовывать приложения или функции представления.
  • Регистрация blueprint на приложении для любого из этих случаев при инициализации расширения Flask.

Blueprint в Flask не является подключаемым приложением, потому что фактически не является приложением — это набор операций, которые могут быть зарегистрированы в приложении, даже несколько раз. Зачем не использовать несколько объектов приложения? Вы можете это сделать (см. Отправка приложения), но ваши приложения будут иметь отдельные конфигурации и будут управляться на уровне WSGI.

Blueprints вместо этого обеспечивают разделение на уровне Flask, совместное использование конфигурации приложения и могут изменять объект приложения по мере необходимости при регистрации. Недостатком является то, что вы не можете отменить регистрацию blueprint после создания приложения, не разрушив весь объект приложения.

Концепция Blueprints

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

Мой первый Blueprint

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

from flask import Blueprint, render_template, abort
from jinja2 import TemplateNotFound

simple_page = Blueprint('simple_page', __name__,
                        template_folder='templates')

@simple_page.route('/', defaults={'page': 'index'})
@simple_page.route('/<page>')
def show(page):
    try:
        return render_template('pages/%s.html' % page)
    except TemplateNotFound:
        abort(404)

Когда вы связываете функцию с помощью декоратора @simple_page.route, blueprint будет записывать намерение зарегистрировать функцию show в приложении при последующей регистрации. Кроме того, он будет добавлять префикс к точке входа функции с именем blueprint, заданным конструктору Blueprint (в этом случае также simple_page). Имя blueprint не изменяет URL, а только точку входа.

Регистрация Blueprints

Как зарегистрировать этот blueprint? Вот так:

from flask import Flask
from yourapplication.simple_page import simple_page

app = Flask(__name__)
app.register_blueprint(simple_page)

Если проверить зарегистрированные правила в приложении, вы найдете следующие:

>>> app.url_map
Map([<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
 <Rule '/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,
 <Rule '/' (HEAD, OPTIONS, GET) -> simple_page.show>])

Первое, очевидно, из самого приложения для статических файлов. Другие два — для функции show blueprint simple_page. Как видите, они также имеют префикс с именем blueprint и разделены точкой (.).

Однако Blueprints также могут быть смонтированы в разных местах:

app.register_blueprint(simple_page, url_prefix='/pages')

И, конечно же, это сгенерированные правила:

>>> app.url_map
Map([<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
 <Rule '/pages/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,
 <Rule '/pages/' (HEAD, OPTIONS, GET) -> simple_page.show>])

Кроме того, вы можете регистрировать blueprints несколько раз, хотя не каждый blueprint может корректно реагировать на это. Фактически, это зависит от реализации blueprint, может ли он быть смонтирован более одного раза.

Ресурсы Blueprint

Blueprints также могут предоставлять ресурсы. Иногда вам может понадобиться создать blueprint только для предоставляемых им ресурсов.

Папка ресурсов Blueprint

Как и для обычных приложений, blueprints считаются содержащимися в папке. Хотя несколько blueprints могут происходить из одной папки, это не обязательно, и это обычно не рекомендуется.

Папка определяется по второму аргументу Blueprint, который обычно __name__. Этот аргумент указывает, какой логический модуль или пакет Python соответствует blueprint. Если он указывает на фактический пакет Python, этот пакет (который является папкой в файловой системе) — папка ресурсов. Если это модуль, пакет, в котором содержится модуль, будет папкой ресурсов. Вы можете получить доступ к свойству Blueprint.root_path, чтобы увидеть, какая это папка ресурсов:

>>> simple_page.root_path
'/Users/username/TestProject/yourapplication'

Чтобы быстро открыть файлы из этой папки, вы можете использовать функцию open_resource():

with simple_page.open_resource('static/style.css') as f:
    code = f.read()

Статические файлы

Blueprint может экспонировать папку со статическими файлами, предоставив путь к папке в файловой системе с аргументом static_folder. Это либо абсолютный путь, либо путь относительно расположения blueprint:

admin = Blueprint('admin', __name__, static_folder='static')

По умолчанию правая часть пути — это место, где он отображается в веб-приложении. Это можно изменить с помощью аргумента static_url_path. Поскольку папка называется static здесь, она будет доступна по адресу url_prefix blueprint + /static. Если у blueprint есть префикс /admin, статический URL будет /admin/static.

Точка входа называется blueprint_name.static. Вы можете генерировать URL для нее с помощью url_for(), как вы делали бы со статической папкой приложения:

url_for('admin.static', filename='style.css')

Однако, если у blueprint нет url_prefix, получить доступ к статической папке blueprint невозможно. Это потому, что URL в этом случае будет /static, и маршрут приложения /static имеет приоритет. В отличие от папок шаблонов, статические папки blueprint не проверяются, если файл не существует в статической папке приложения.

Шаблоны

Если вы хотите, чтобы blueprint экспонировал шаблоны, вы можете сделать это, предоставив параметр template_folder конструктору Blueprint:

admin = Blueprint('admin', __name__, template_folder='templates')

Для статических файлов путь может быть абсолютным или относительным к папке ресурсов blueprint.

Папка шаблонов добавляется в путь поиска шаблонов, но с более низким приоритетом, чем фактическая папка шаблонов приложения. Таким образом, вы легко можете переопределить шаблоны, предоставляемые blueprint, в фактическом приложении. Это также означает, что если вы не хотите, чтобы шаблон blueprint случайно переопределялся, убедитесь, что ни один другой blueprint или фактическое приложение шаблона не имеет того же относительного пути. Когда несколько blueprints предоставляют один и тот же относительный путь шаблона, первый зарегистрированный blueprint имеет приоритет над другими.

Итак, если у вас есть blueprint в папке yourapplication/admin и вы хотите отобразить шаблон 'admin/index.html', и вы предоставили templates в качестве template_folder, вам нужно создать файл, подобный этому: yourapplication/admin/templates/admin/index.html. Причина дополнительной папки admin — избежать переопределения шаблона шаблоном index.html в фактической папке шаблонов приложения.

Чтобы еще раз подчеркнуть это: если у вас есть blueprint с именем admin и вы хотите отобразить шаблон index.html, специфичный для этого blueprint, лучше всего организовать шаблоны так:

yourpackage/
    blueprints/
        admin/
            templates/
                admin/
                    index.html
            __init__.py

А затем, когда вы захотите отобразить шаблон, используйте admin/index.html в качестве имени для поиска шаблона. Если у вас возникнут проблемы с загрузкой правильных шаблонов, включите переменную конфигурации EXPLAIN_TEMPLATE_LOADING, которая укажет Flask на вывод шагов, которые он выполняет для поиска шаблонов при каждом вызове render_template.

Создание URL

Если вы хотите создать ссылку на другую страницу, вы можете использовать функцию url_for() так же, как обычно, только добавляя префикс к точке входа URL с именем blueprint и точкой (.):

url_for('admin.index')

Кроме того, если вы находитесь в функции представления blueprint или отображаемом шаблоне и хотите ссылаться на другую точку входа того же blueprint, вы можете использовать относительные редиректы, добавляя только точку к точке входа:

url_for('.index')

Это будет ссылка на admin.index в случае, если текущий запрос был передан в любую другую точку входа blueprint администратора.

Обработчики ошибок

Blueprints поддерживают декоратор errorhandler так же, как и объект приложения Flask, поэтому легко создавать пользовательские страницы ошибок, специфичные для Blueprint.

Вот пример для исключения «404 Страница не найдена»:

@simple_page.errorhandler(404)
def page_not_found(e):
    return render_template('pages/404.html')

Большинство обработчиков ошибок будут работать как ожидается; однако есть исключение, касающееся обработчиков исключений 404 и 405. Эти обработчики ошибок вызываются только из соответствующего raise оператора или вызова abort в другой функции представления blueprint; они не вызываются, например, при недопустимом доступе к URL. Это потому, что blueprint не «владеет» определенным пространством URL, поэтому экземпляр приложения не может знать, какой обработчик ошибок blueprint он должен запустить, если ему предоставлен недопустимый URL. Если вы хотите выполнить разные стратегии обработки для этих ошибок на основе префиксов URL, они могут быть определены на уровне приложения с помощью прокси-объекта request:

@app.errorhandler(404)
@app.errorhandler(405)
def _handle_api_error(ex):
    if request.path.startswith('/api/'):
        return jsonify_error(ex)
    else:
        return ex

Дополнительная информация об обработке ошибок см. в Пользовательские страницы ошибок.

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

Spec-Zone.ru

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