.. _blueprints: Модульные приложения Flask с использованием blueprint'ов ======================================================== .. versionadded:: 0.7 Flask использует концепцию *blueprint'ов* ("blueprint" - "эскиз") для создания компонентов приложений и поддержки общих шаблонов внутри приложения или между приложениями. Blueprint'ы могут как значительно упростить большие приложения, так и предоставить общий механизм регистрации в приложении операций из расширений Flask. Объект :class:`Blueprint` работает аналогично объекту приложения :class:`Flask`, но в действительности он не является приложением. Обычно это лишь *эскиз* для сборки или расширения приложения. Для чего нужны blueprint'ы? --------------------------- Blueprint'ы во Flask могут пригодиться в случае, если нужно: * Разделить приложения на набор blueprint'ов. Они идеальны для больших приложений; проект должен создать объект приложения, инициализировав несколько расширений, и зарегистрировав набор blueprint'ов. * Зарегистрировать blueprint в приложении по определённом префиксу URL и/или в поддомене. Параметры в префиксе URL или поддомене становятся обычными аргументами представлений (со значениями по умолчанию) для всех функций представлений в blueprint'е. * Зарегистрировать blueprint несколько раз в приложении с разными правилами URL. * Предоставить фильтры шаблонов, статический файлы, шаблоны и другие вспомогательные средства с помощью blueprint'ов. Blueprint не является реализацией приложения или функций представлений. * Зарегистрировать blueprint в приложении в любом из этих случаев при инициализации расширения Flask. Blueprint во Flask не является подключаемым приложением, потому что это на самом деле не приложение -- это набор операций, которые могут быть зарегистрированы в приложении, возможно даже не один раз. Почему бы не воспользоваться несколькими объектами приложений? Вы можете это сделать (обратитесь к разделу :ref:`app-dispatch`), но ваши приложения будут иметь раздельные файлы конфигурации и будут управляться слоем WSGI. Вместо этого, blueprint'ы предоставляют разделение на уровне Flask, позволяя использовать общий файл конфигурации приложения и могут менять объект приложения необходимым образом при регистрации. Побочным эффектом будет невозможность отменить регистрацию blueprint'а, если приложение уже было создано, если только не уничтожить целиком весь объект приложения. Концепция blueprint'ов ---------------------- Основная концепция blueprint'ов заключается в том, что они записывают операции для выполнения при регистрации в приложении. Flask связывает функции представлений с blueprint'ами при обработке запросов и генерировании 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('/') def show(page): try: return render_template('pages/%s.html' % page) except TemplateNotFound: abort(404) При связывании функции при помощи декоратора ``@simple_page.route``, blueprint записывает намерение зарегистрировать в приложении функцию `show`, когда blueprint будет зарегистрирован. Кроме того, декоратор предварит название конечной точки префиксом - именем blueprint'а, который был указан конструктору :class:`Blueprint` (в данном случае это тоже ``simple_page``). Регистрация blueprint'ов ------------------------ Как теперь зарегистрировать этот blueprint? Например, так:: from flask import Flask from yourapplication.simple_page import simple_page app = Flask(__name__) app.register_blueprint(simple_page) Если теперь посмотреть на правила, зарегистрированные в приложении, то можно обнаружить следующее:: [' (HEAD, OPTIONS, GET) -> static>, ' (HEAD, OPTIONS, GET) -> simple_page.show>, simple_page.show>] Первым обычно является правило для статических файлов самого приложения. Следующие два правила - правила для функции `show` из blueprint'а ``simple_page``. Как можно заметить, они тоже предварены именем blueprint'а и отделены от него точкой (``.``). Однако, blueprint'ы можно связывать с другими местами:: app.register_blueprint(simple_page, url_prefix='/pages') И, чтобы убедиться в этом, посмотрим на правила, сгенерированные на этот раз:: [' (HEAD, OPTIONS, GET) -> static>, ' (HEAD, OPTIONS, GET) -> simple_page.show>, simple_page.show>] Плюс ко всему, можно зарегистрировать blueprint'ы несколько раз, хотя не каждый blueprint будет работать правильно. Это зависит от того, был ли реализован blueprint'е с учётом возможности многократного монтирования. Ресурсы blueprint'а ------------------- Blueprint'ы могут, кроме всего прочего, предоставлять ресурсы. Иногда может потребоваться ввести дополнительный blueprint только ради предоставления ресурсов. Каталог ресурсов blueprint'а ```````````````````````````` Как и обычные приложения, blueprint'ы задуманы для размещения в отдельном каталоге. Хотя несколько blueprint'ов можно разместить в одном и том же каталоге, так делать не рекомендуется. Имя каталога берётся из второго аргумента :class:`Blueprint`'а, которым обычно является `__name__`. Этот аргумент указывает, какой логический модуль или пакет Python соответствует blueprint'у. Если он указывает на существующий пакет Python (который является каталогом файловой системы), то он и будет каталогом ресурсов. Если это модуль, то каталогом ресурсов будет тот каталог, в котором содержится модуль. Можно обратиться к свойству :attr:`Blueprint.root_path`, чтобы увидеть, что это за каталог:: >>> simple_page.root_path '/Users/username/TestProject/yourapplication' Для быстрого открытия ресурсов из этого каталога можно воспользоваться функцией :meth:`~Blueprint.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``, он будет располагаться внутри каталога blueprint'а и будет называться ``static``. В данном случае при регистрации blueprint'а в каталоге ``/admin``, каталог ``static`` будет находиться в ``/admin/static``. Конечная точка будет иметь имя `blueprint_name.static`, так что можно генерировать URL'ы точно так же, как это делается для статического каталога приложения:: url_for('admin.static', filename='style.css') Шаблоны ``````` Если нужно выставить наружу каталог с шаблонами, это можно сделать указав параметр `template_folder` конструктору :class:`Blueprint`:: admin = Blueprint('admin', __name__, template_folder='templates') Как и в случае статических файлов, путь может быть абсолютным или располагаться в каталоге ресурсов blueprint'а. Каталог шаблона добавляется к пути поиска шаблонов, но с меньшим приоритетом, чем каталог шаблонов самого приложения. Таким образом, можно легко заменить шаблоны blueprint'а в самом приложении. Например, если есть blueprint в каталоге ``yourapplication/admin`` и нужно отрисовать шаблон ``'admin/index.html'``, а в параметре `template_folder` указан каталог `templates`, тогда нужно создать файл ``yourapplication/admin/templates/admin/index.html``. Генерирование URL'ов -------------------- Если нужно вставить ссылку с одной страницы на другую, можно воспользоваться функцией :func:`url_for`, как обычно: нужно просто добавить к конечной точке URL'а префикс с именем blueprint'а и точкой (``.``):: url_for('admin.index') Наконец, если в функции представления blueprint'а или в отрисованном шаблоне нужно добавить ссылку на другую конечную точку того же blueprint'а, можно воспользоваться относительным перенаправлением, добавив префикс, состоящий только из точки:: url_for('.index') Получится ссылка на ``admin.index`` в случае обработки текущего запроса в любой другой конечной точке blueprint'а. Обработчики ошибок ------------------ Точно так же, как и объект приложения :class:`Flask`, Blueprint'ы поддерживают декоратор обработчика ошибок , так что создать blueprint-специфичные заданные программистом страницы ошибок просто. Вот пример для обработки исключения "404 Page Not Found":: @simple_page.errorhandler(404) def page_not_found(e): return render_template('pages/404.html') За дополнительной информацией по обработке ошибок обратитесь к разделу :ref:`errorpages`. `Оригинал этой страницы `_