.. _config: Обработка конфигурации Flask ============================ .. versionadded:: 0.3 Приложения требуют настройки. Здесь описаны различные настройки, которые можно менять в зависимости от окружения, в котором работает приложение: переключение режима отладки, настройки секретного ключа и т.п. Flask спроектирован так, что обычно требует настройки при запуске приложения. Вы можете вшить настройки в код, что не так уж плохо для многих небольших приложений, но имеются способы лучше. Вне зависимости от того, каким образом загружена конфигурация, существует объект конфигурации, содержащий загруженные параметры: атрибут :attr:`~flask.Flask.config` объекта :class:`~flask.Flask`. Это место, где Flask содержит свои настройки, а также то место, куда расширения могут поместить собственные настройки. Но здесь можно размещать и конфигурацию вашего приложения. Основы конфигурации ------------------- :attr:`~flask.Flask.config` на самом деле является подклассом словаря и может изменяться точно так же, как и любой словарь:: app = Flask(__name__) app.config['DEBUG'] = True Некоторые параметры конфигурации передаются в объект :attr:`~flask.Flask`, которые тоже можно читать и писать:: app.debug = True Для обновления нескольких ключей за раз можно воспользоваться методом словаря :meth:`dict.update`:: app.config.update( DEBUG=True, SECRET_KEY='...' ) Встроенные параметры конфигурации --------------------------------- Сам Flask использует следующие параметры конфигурации: .. tabularcolumns:: |p{6.5cm}|p{8.5cm}| ================================= ========================================= ``DEBUG`` Включить/выключить режим отладки. ``TESTING`` Включить/выключить режим тестирования. ``PROPAGATE_EXCEPTIONS`` Явное включение или отключение исключений. Если не задано или явным образом задано значение `None`, то подразумевается истина, если истиной является `TESTING` или `DEBUG`. ``PRESERVE_CONTEXT_ON_EXCEPTION`` По умолчанию в режиме отладки при возникновении исключения контекст запроса не извлекается из стека, позволяя отладчику анализировать данные. Такое поведение можно отключить с помощью этого параметра. Также можно воспользоваться этим параметром для его принудительного включения, если это может помочь в отладке приложений в эксплуатации (однако, это не рекомендуется). ``SECRET_KEY`` Секретный ключ. ``SESSION_COOKIE_NAME`` Имя переменной (cookie) браузера для хранения сеанса. ``SESSION_COOKIE_DOMAIN`` Домен переменной браузера, используемой для хранения сеанса. Если не задан, переменная браузера будет действительной для всех поддоменов ``SERVER_NAME``. ``SESSION_COOKIE_PATH`` Путь к переменной браузера, используемой для хранения сеанса. Если не задан, переменная браузера будет действительной для всех ``APPLICATION_ROOT``, если не задано значение ``'/'``. ``SESSION_COOKIE_HTTPONLY`` Указывает, должен ли у переменной браузера устанавливаться флаг httponly (что защищает переменную от доступа со стороны скриптов, работающих внутри браузера - ``прим. перев.``). По умолчанию - `True`. ``SESSION_COOKIE_SECURE`` Указывает, должен ли у переменной браузера устанавливаться флаг secure (что позволяет передавать переменную только по защищённому протоколу HTTPS - ``прим. перев.``). По умолчанию - `False`. ``PERMANENT_SESSION_LIFETIME`` Непрерывное время жизни сеанса, как объект :class:`datetime.timedelta`. Начиная с Flask 0.8 этот параметр может быть задан в виде целого числа с количеством секунд. ``USE_X_SENDFILE`` Включить/отключить x-sendfile. (При использовании этой возможности представление может вернуть специально сформированный ответ со ссылкой на статический файл. Получив такой ответ от представления, веб-сервер отдаёт клиенту вместо ответа представления сам статический файл, найдя его по ссылке в локальной файловой системе. Это позволяет перенести нагрузку по отдаче больших файлов на веб-сервер, если перед отдачей файла представление должно решить, можно ли отдавать этот файл клиенту и какой именно файл нужно отдать по этой ссылке - ``прим. перев.``) ``LOGGER_NAME`` Имя средства журналирования. ``SERVER_NAME`` Имя и номер порта сервера. Необходимо для поддержки поддоменов (например: ``'myapp.dev:5000'``). Отметим, что localhost не поддерживает поддомены, поэтому установка параметра в значение “localhost” не поможет. Настройка ``SERVER_NAME`` также по умолчанию включает генерацию URL'ов без контекста запроса, но с контекстом приложения. ``APPLICATION_ROOT`` Если приложение не занимает целый домен или поддомен, с помощью этого параметра можно задать путь к настроенному приложению. Значение этого параметра используется в качестве пути к переменной браузера для хранения сеанса. Если используются домены, значением этого параметра должно быть ``None``. ``MAX_CONTENT_LENGTH`` Если задать значение в байтах, Flask будет отклонять входящие запросы, объём содержимого которых больше этого значения, возвращая код статуса 413. ``SEND_FILE_MAX_AGE_DEFAULT``: По умолчанию задаёт время кэширования файла для использования совместно с :meth:`~flask.Flask.send_static_file` (обработчик статических файлов по умолчанию) и :func:`~flask.send_file`, в секундах. Заменить это значение для каждого файла индивидуально можно с помощью обработчика :meth:`~flask.Flask.get_send_file_max_age` :class:`~flask.Flask` или :class:`~flask.Blueprint`. По умолчанию - 43200 (12 часов). ``TRAP_HTTP_EXCEPTIONS`` Если ``True``, Flask не выполняет обработчиков ошибок исключений HTTP, но вместо этого трактует исключение как любое другое и передаёт исключение выше. Этот параметр полезен для отладки сложных случаев, когда нужно найти, где именно произошло исключение HTTP. ``TRAP_BAD_REQUEST_ERRORS`` Внутренние структуры данных Werkzeug, работающие с данными запроса порождают ошибки с особым ключом, также являющимся исключением запроса. Также, многие операции могут неявно приводить к исключениям BadRequest в случае ошибок целостности. Поскольку для отладки важно знать, где именно произошла ошибка, этот флаг может использоваться для отладки в подобных случаях. Если этот параметр истинен (``True``), произойдёт обычная выдача результата трассировки. ``PREFERRED_URL_SCHEME`` Схема, которую нужно использовать для генерации URL'ов, если она не указана явно. По умолчанию - ``http``. ================================= ========================================= .. admonition:: Подробнее о ``SERVER_NAME`` ``SERVER_NAME`` - это параметр, который используется для поддержки поддоменов. Flask не может догадаться о том, какая часть доменного имени является поддоменом, не зная имя сервера. Этот же параметр используется для настройки переменной браузера, в которой хранится сеанс. Помните, что не только Flask не может узнать поддомен, ваш веб-браузер тоже не может. Большинство соверменных браузеров не разрешают междоменные переменные браузера, если в имени сервера нет точек. Поэтому если имя сервера ``'localhost'``, вы не сможете задать переменную браузера для ``'localhost'`` и каждого из его поддоменов. В этом случае выберите другое имя сервера, например ``'myapplication.local'`` и добавьте это имя и поддомены, которые вы хотите использовать, в файл hosts или настройте локальный `bind`_. .. _bind: https://www.isc.org/software/bind .. versionadded:: 0.4 ``LOGGER_NAME`` .. versionadded:: 0.5 ``SERVER_NAME`` .. versionadded:: 0.6 ``MAX_CONTENT_LENGTH`` .. versionadded:: 0.7 ``PROPAGATE_EXCEPTIONS``, ``PRESERVE_CONTEXT_ON_EXCEPTION`` .. versionadded:: 0.8 ``TRAP_BAD_REQUEST_ERRORS``, ``TRAP_HTTP_EXCEPTIONS``, ``APPLICATION_ROOT``, ``SESSION_COOKIE_DOMAIN``, ``SESSION_COOKIE_PATH``, ``SESSION_COOKIE_HTTPONLY``, ``SESSION_COOKIE_SECURE`` .. versionadded:: 0.9 ``PREFERRED_URL_SCHEME`` Задание конфигурации с помощью файлов ------------------------------------- Конфигурация становится более удобной, если разместить её в отдельном файле. Лучше, если он находится за пределами пакета с приложением. Это позволяет создавать пакеты и распространять приложения с помощью различных инструментов обработки пакетов (:ref:`distribute-deployment`) и впоследствии - изменять конфигурацию. Далее показан обычный пример::: app = Flask(__name__) app.config.from_object('yourapplication.default_settings') app.config.from_envvar('YOURAPPLICATION_SETTINGS') Сначала грузится конфигурация из модуля `yourapplication.default_settings`, а затем её значения заменяет содержимое файла, указанного в переменной окружения :envvar:`YOURAPPLICATION_SETTINGS`. Эта переменная окружения может быть задана в Linux или OS X при помощи команды export оболочки перед запуском сервера:: $ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg $ python run-app.py * Running on http://127.0.0.1:5000/ * Restarting with reloader... В системах Windows воспользуйтесь встроенной командой `set`:: >set YOURAPPLICATION_SETTINGS=\path\to\settings.cfg Файлы конфигурации являются обычными файлами Python. В объект конфигурации сохраняются только переменные с именами в верхнем регистре, так что убедитесь в том, что имена ваших параметров заданы в верхнем регистре. Вот пример файла конфигурации:: # Пример конфигурации DEBUG = False SECRET_KEY = '?\xbf,\xb4\x8d\xa3"<\x9c\xb0@\x0f5\xab,w\xee\x8d$0\x13\x8b83' Убедитесь в том, что файл загружается как можно раньше, чтобы расширения могли получить доступ к собственным настройкам при запуске. Существуют другие методы загрузки объекта конфигурации из отдельных файлов. За более полной информацией обратитесь к документации объекта :class:`~flask.Config`. Лучшие способы задания конфигурации ----------------------------------- Недостаток описанного выше подхода заключается в усложнении тестирования. Нет стопроцентного способа решения этой проблемы, но вот несколько рекомендаций опытных пользователей: 1. Создайте ваше приложение внутри функции и зарегистрируйте в ней blueprint'ы. Таким образом вы можете создать несколько экземпляров вашего приложения с разными конфигурациями, что значительно упростит модульное тестирование. Вы можете воспользоваться функцией, чтобы передать в неё необходимую конфигурацию. 2. Не пишите код, которому требуется конфигурация при импорте. Если ограничиться чтением конфигурации по запросу, возможно будет переконфигурировать объект позже. Режим разработки и режим эксплуатации ------------------------------------- Большинству приложений нужно более одной конфигурации. По меньшей мере нужна отдельная конфигурация для рабочего сервера и ещё одна для разработки. Простейший способ управления ими - это создать конфигурацию по умолчанию, которая загружается всегда и которую можно поместить в систему управления версиями, и частичные конфигурации, которые заменяют необходимые значения следующим образом:: app = Flask(__name__) app.config.from_object('yourapplication.default_settings') app.config.from_envvar('YOURAPPLICATION_SETTINGS') Теперь просто создайте отдельный файл `config.py`, выполните команду export ``YOURAPPLICATION_SETTINGS=/path/to/config.py`` и готово. Однако, существуют альтернативные способы. Например, можно воспользоваться импортом и подклассами. В мире Django распространён следующий способ: сделать явный импорт конфигурации, добавив строку ``from yourapplication.default_settings import *`` в начале файла, а затем заменить значения вручную. Можно сделать также, затем взять из переменной окружения вида ``YOURAPPLICATION_MODE`` необходимый режим - `production`, `development` и т.п., а затем импортировать заранее определённые файлы, основываясь на этом значении. Другой любопытный способ - воспользоваться классами и наследованием конфигурации:: class Config(object): DEBUG = False TESTING = False DATABASE_URI = 'sqlite://:memory:' class ProductionConfig(Config): DATABASE_URI = 'mysql://user@localhost/foo' class DevelopmentConfig(Config): DEBUG = True class TestingConfig(Config): TESTING = True Для включения такой конфигурации, вам просто нужно вызвать :meth:`~flask.Config.from_object`:: app.config.from_object('configmodule.ProductionConfig') There are many different ways and it's up to you how you want to manage your configuration files. However here a list of good recommendations: - keep a default configuration in version control. Either populate the config with this default configuration or import it in your own configuration files before overriding values. - use an environment variable to switch between the configurations. This can be done from outside the Python interpreter and makes development and deployment much easier because you can quickly and easily switch between different configs without having to touch the code at all. If you are working often on different projects you can even create your own script for sourcing that activates a virtualenv and exports the development configuration for you. - Use a tool like `fabric`_ in production to push code and configurations separately to the production server(s). For some details about how to do that, head over to the :ref:`fabric-deployment` pattern. Есть много разных способов, которые можно выбрать для управления файлами конфигурации. Вот список хороших советов: - Храните файл конфигурации по умолчанию в системе управления версиями. Заполните объект конфигурации значениями по умолчанию или импортируйте его в ваших собственных файлах конфигурации перед тем, как заменить значения. - Воспользуйтесь переменной окружения для переключения между конфигурациями. Это можно сделать вне интерпретатора Python и это позволит упростить разработку и развёртывание, потому что вы можете быстро и легко переключаться между разными конфигурациями, совсем не прикасаясь к коду. Если вы часто работаете над разными проектами, можно создать собственный скрипт, который будет определять текущий каталог проекта, активировать virtualenv и экспортировать конфигурацию режима разработки. - Используйте инструмент `fabric`_ для внесения изменений на сервер эксплуатации и раздельных конфигураций на серверы эксплуатации. За более подробным описанием того, как это сделать, обратитесь к главе :ref:`fabric-deployment`. .. _fabric: http://fabfile.org/ .. _instance-folders: Каталоги экземпляров -------------------- .. versionadded:: 0.8 Во Flask 0.8 появились каталоги экземпляров. Flask долгое время позволял ссылаться на пути относительно каталога приложения (с помощью :attr:`Flask.root_path`). Поэтому многие разработчики хранили конфигурацию рядом с приложением. К несчастью, это возможно только если приложение не находится внутри пакета, так как в таком случае root_path указывает внутрь пакета. Во Flask 0.8 был введён новый атрибут: :attr:`Flask.instance_path`. Он вводит новое понятие, которое называется “каталогом экземпляра”. Каталог экземпляра задуман как каталог, не управляемый системой контроля версий и относящийся к развёрнутому приложению. Это подходящее место для того, чтобы поместить в него файлы, изменяемые в процессе работы или файлы конфигурации. Можно явным образом указать путь к каталогу экземпляра при создании приложения Flask или можно разрешить Flask'у самому выбрать каталог экземпляра. Чтобы задать его явным образом, воспользуйтесь параметром `instance_path`:: app = Flask(__name__, instance_path='/path/to/instance/folder') Помните, что если этот путь указан, он *должен* быть абсолютным. Если параметр `instance_path` не указан, по умолчанию используются следующие места: - Не установленный модуль:: /myapp.py /instance - Не установленный пакет:: /myapp /__init__.py /instance - Установленный модуль или пакет:: $PREFIX/lib/python2.X/site-packages/myapp $PREFIX/var/myapp-instance ``$PREFIX`` - это префикс, с которым установлен Python. Это может быть каталог ``/usr`` или путь в каталоге с виртуальным окружением, созданном virtualenv. Можно вывести на экран значение ``sys.prefix``, чтобы увидеть его действительное значение. Как только стало возможным загружать объект конфигурации из файлов с относительными именами, мы добавили возможность загружать файлы с именами относительно каталога экземпляра. При помощи переключателя `instance_relative_config` в конструкторе приложения можно указать, должны ли интерпретироваться относительные пути файлов “относительно корня приложения” (по умолчанию) или “относительно каталога экземпляра”:: app = Flask(__name__, instance_relative_config=True) Ниже представлен полный пример настройки Flask для предварительной загрузки конфигурации из модуля и последующей замены параметров значениями из файла в каталоге конфигурации, если он существует:: app = Flask(__name__, instance_relative_config=True) app.config.from_object('yourapplication.default_settings') app.config.from_pyfile('application.cfg', silent=True) Путь к каталогу экземпляра может быть найден при помощи :attr:`Flask.instance_path`. Flask также предоставляет более короткий способ открытия файлов из каталога экземпляра при помощи :meth:`Flask.open_instance_resource`. Вот пример для обоих способов:: filename = os.path.join(app.instance_path, 'application.cfg') with open(filename) as f: config = f.read() # или при помощи open_instance_resource: with app.open_instance_resource('application.cfg') as f: config = f.read() Примечания переводчика ---------------------- В качестве перевода для термина ``cookie`` было использовано понятие "переменных бразуера". Информация о флагах `httponly` и `secure` взята из статьи `HTTP cookie `_. Информация о `x-sendfile` взята из статьи `Передача файлов с помощью XSendfile с помощью NGINX `_.