Spec-Zone.ru › Flask 2.2

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

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

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

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

Зачем использовать 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(f'pages/{page}.html')
    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, может ли он быть смонтирован более одного раза.

Вложенные Blueprints

Можно зарегистрировать blueprint в другом blueprint.

parent = Blueprint('parent', __name__, url_prefix='/parent')
child = Blueprint('child', __name__, url_prefix='/child')
parent.register_blueprint(child)
app.register_blueprint(parent)

Вложенный blueprint получит имя родительского blueprint в качестве префикса к своему имени, а вложенные URL будут иметь префикс с URL префиксом родительского blueprint.

url_for('parent.child.create')
/parent/child/create

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

Ресурсы Blueprints

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

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

Как и в обычных приложениях, 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 в случае, если текущий запрос был обработан любой другой точкой входа admin blueprint.

Обработчики ошибок 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=str(ex)), ex.code
    else:
        return ex

См. Обработка ошибок приложения.

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

Spec-Zone.ru

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