.. _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 этот параметр может быть задан в виде целого числа с количеством секунд. ``SESSION_REFRESH_EACH_REQUEST`` Этот флаг контролирует, как будут обновляться постоянные сессии. Если установлен в `True` (по умолчанию), cookies будут обновляться при каждом запросе, что автоматически подтолкнёт вперёд окончание их срока жизни. Если установлен в `False`, заголовок `set-cookie` посылается только в случае внесения изменений в сессию. Не влияет на не постоянные сессии. ``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``. ``JSON_AS_ASCII`` По умолчанию Flask сериализует объекты к JSON, представленному в виде ASCII. Если ``False``, Flask не будет кодировать в ASCII, а выводимые строки будут как есть, то есть в виде строк в формате unicode. Затем, ``json-ификация`` автоматически переведёт их к кодировке ``utf-8`` для дальнейшей доставки для экземпляра. ``JSON_SORT_KEYS`` По умолчанию Flask сериализует объекты JSON таким способом, что ключи становятся упорядоченными. Это делается, чтобы гарантировать, что независимо от значения хэша словаря, возвращаемое значение будет таким, чтобы не замусоривать внешние HTTP- кэши. Вы можете переопределить поведение по умолчанию через изменение этой переменной. Это не рекомендовано, но может дать вам выигрыш в производительности ценой худшей кэшируемости данных. ``JSONIFY_PRETTYPRINT_REGULAR`` Если ``True`` (по умолчанию), ответы json-ификации будут распечатаны, если они не запрашивались объектом XMLHttpRequest (который контролируется заголовком ``X-Requested-With``) ``TEMPLATES_AUTO_RELOAD`` Flask проверяет, был ли изменён шаблон каждый раз, когда он запрашивается, и перезагружает его в случае такой необходимости. Однако это происходит ценой увеличения дискового ввода-вывода, и может появиться жизненная необходимость отключить данную особенность путём установки этого ключа в ``False``. Данная опция не оказывает влияния при работе в режиме отладки. ================================= ========================================= .. 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`` .. versionadded:: 0.10 ``JSON_AS_ASCII``, ``JSON_SORT_KEYS``, ``JSONIFY_PRETTYPRINT_REGULAR`` .. versionadded:: 1.0 ``SESSION_REFRESH_EACH_REQUEST`` .. versionadded:: 1.0 ``TEMPLATES_AUTO_RELOAD`` Задание конфигурации с помощью файлов ------------------------------------- Конфигурация становится более удобной, если разместить её в отдельном файле. Лучше, если он находится за пределами пакета с приложением. Это позволяет создавать пакеты и распространять приложения с помощью различных инструментов обработки пакетов (: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') Есть много разных способов, которые можно выбрать для управления файлами конфигурации. Вот список хороших советов: - Храните файл конфигурации по умолчанию в системе управления версиями. Заполните объект конфигурации значениями по умолчанию или импортируйте его в ваших собственных файлах конфигурации перед тем, как заменить значения. - Воспользуйтесь переменной окружения для переключения между конфигурациями. Это можно сделать вне интерпретатора 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 `_. `Оригинал этой страницы `_