Spec-Zone.ru › Flask 2.0

Модульные приложения с 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(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 также могут предоставлять ресурсы. Иногда вам может потребоваться ввести 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 имеет приоритет. В отличие от папок шаблонов, папки статических файлов blueprints не проверяются, если файла нет в папке статических файлов приложения.

Шаблоны

Если вы хотите, чтобы 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 "admin".

Обработчики ошибок 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 в другой функции представления в рамках шаблона; они не вызываются, например, при доступе к недействительному URL. Это происходит потому, что шаблон не «владеет» определенным пространством URL, поэтому экземпляр приложения не может определить, какой обработчик ошибок шаблона следует запустить, если предоставлен недействительный 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–2021 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.0.x/blueprints/

Spec-Zone.ru

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