Обработка конфигурации Flask¶
Добавлено в версии 0.3.
Приложения требуют настройки. Здесь описаны различные настройки, которые можно менять в зависимости от окружения, в котором работает приложение: переключение режима отладки, настройки секретного ключа и т.п.
Flask спроектирован так, что обычно требует настройки при запуске приложения. Вы можете вшить настройки в код, что не так уж плохо для многих небольших приложений, но имеются способы лучше.
Вне зависимости от того, каким образом загружена конфигурация, существует
объект конфигурации, содержащий загруженные параметры: атрибут
config
объекта Flask
. Это место,
где Flask содержит свои настройки, а также то место, куда расширения могут
поместить собственные настройки. Но здесь можно размещать и конфигурацию
вашего приложения.
Основы конфигурации¶
config
на самом деле является подклассом словаря и
может изменяться точно так же, как и любой словарь:
app = Flask(__name__)
app.config['DEBUG'] = True
Некоторые параметры конфигурации передаются в объект Flask
,
которые тоже можно читать и писать:
app.debug = True
Для обновления нескольких ключей за раз можно воспользоваться методом
словаря dict.update()
:
app.config.update(
DEBUG=True,
SECRET_KEY='...'
)
Встроенные параметры конфигурации¶
Сам Flask использует следующие параметры конфигурации:
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 |
Непрерывное время жизни сеанса, как
объект 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 : |
По умолчанию задаёт время кэширования
файла для использования совместно с
send_static_file()
(обработчик статических файлов по
умолчанию) и send_file() ,
в секундах. Заменить это значение для
каждого файла индивидуально можно с
помощью обработчика
get_send_file_max_age()
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 .
Данная опция не оказывает влияния при работе
в режиме отладки. |
Подробнее о SERVER_NAME
SERVER_NAME
- это параметр, который используется для поддержки
поддоменов. Flask не может догадаться о том, какая часть доменного
имени является поддоменом, не зная имя сервера. Этот же параметр
используется для настройки переменной браузера, в которой хранится сеанс.
Помните, что не только Flask не может узнать поддомен, ваш веб-браузер
тоже не может. Большинство соверменных браузеров не разрешают
междоменные переменные браузера, если в имени сервера нет точек.
Поэтому если имя сервера 'localhost'
, вы не сможете задать переменную
браузера для 'localhost'
и каждого из его поддоменов. В этом случае
выберите другое имя сервера, например 'myapplication.local'
и
добавьте это имя и поддомены, которые вы хотите использовать, в файл
hosts или настройте локальный bind.
Добавлено в версии 0.4: LOGGER_NAME
Добавлено в версии 0.5: SERVER_NAME
Добавлено в версии 0.6: MAX_CONTENT_LENGTH
Добавлено в версии 0.7: PROPAGATE_EXCEPTIONS
, PRESERVE_CONTEXT_ON_EXCEPTION
Добавлено в версии 0.8: TRAP_BAD_REQUEST_ERRORS
, TRAP_HTTP_EXCEPTIONS
,
APPLICATION_ROOT
, SESSION_COOKIE_DOMAIN
,
SESSION_COOKIE_PATH
, SESSION_COOKIE_HTTPONLY
,
SESSION_COOKIE_SECURE
Добавлено в версии 0.9: PREFERRED_URL_SCHEME
Добавлено в версии 0.10: JSON_AS_ASCII
, JSON_SORT_KEYS
, JSONIFY_PRETTYPRINT_REGULAR
Добавлено в версии 1.0: SESSION_REFRESH_EACH_REQUEST
Добавлено в версии 1.0: TEMPLATES_AUTO_RELOAD
Задание конфигурации с помощью файлов¶
Конфигурация становится более удобной, если разместить её в отдельном файле. Лучше, если он находится за пределами пакета с приложением. Это позволяет создавать пакеты и распространять приложения с помощью различных инструментов обработки пакетов (distribute-deployment) и впоследствии - изменять конфигурацию.
Далее показан обычный пример::
app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')
Сначала грузится конфигурация из модуля
yourapplication.default_settings, а затем её значения заменяет
содержимое файла, указанного в переменной окружения
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'
Убедитесь в том, что файл загружается как можно раньше, чтобы расширения
могли получить доступ к собственным настройкам при запуске. Существуют
другие методы загрузки объекта конфигурации из отдельных файлов. За более
полной информацией обратитесь к документации объекта Config
.
Лучшие способы задания конфигурации¶
Недостаток описанного выше подхода заключается в усложнении тестирования. Нет стопроцентного способа решения этой проблемы, но вот несколько рекомендаций опытных пользователей:
- Создайте ваше приложение внутри функции и зарегистрируйте в ней blueprint’ы. Таким образом вы можете создать несколько экземпляров вашего приложения с разными конфигурациями, что значительно упростит модульное тестирование. Вы можете воспользоваться функцией, чтобы передать в неё необходимую конфигурацию.
- Не пишите код, которому требуется конфигурация при импорте. Если ограничиться чтением конфигурации по запросу, возможно будет переконфигурировать объект позже.
Режим разработки и режим эксплуатации¶
Большинству приложений нужно более одной конфигурации. По меньшей мере нужна отдельная конфигурация для рабочего сервера и ещё одна для разработки. Простейший способ управления ими - это создать конфигурацию по умолчанию, которая загружается всегда и которую можно поместить в систему управления версиями, и частичные конфигурации, которые заменяют необходимые значения следующим образом:
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
Для включения такой конфигурации, вам просто нужно вызвать
from_object()
:
app.config.from_object('configmodule.ProductionConfig')
Есть много разных способов, которые можно выбрать для управления файлами конфигурации. Вот список хороших советов:
- Храните файл конфигурации по умолчанию в системе управления версиями. Заполните объект конфигурации значениями по умолчанию или импортируйте его в ваших собственных файлах конфигурации перед тем, как заменить значения.
- Воспользуйтесь переменной окружения для переключения между конфигурациями. Это можно сделать вне интерпретатора Python и это позволит упростить разработку и развёртывание, потому что вы можете быстро и легко переключаться между разными конфигурациями, совсем не прикасаясь к коду. Если вы часто работаете над разными проектами, можно создать собственный скрипт, который будет определять текущий каталог проекта, активировать virtualenv и экспортировать конфигурацию режима разработки.
- Используйте инструмент fabric для внесения изменений на сервер эксплуатации и раздельных конфигураций на серверы эксплуатации. За более подробным описанием того, как это сделать, обратитесь к главе fabric-deployment.
Каталоги экземпляров¶
Добавлено в версии 0.8.
Во Flask 0.8 появились каталоги экземпляров. Flask долгое время позволял
ссылаться на пути относительно каталога приложения (с помощью
Flask.root_path
). Поэтому многие разработчики хранили конфигурацию
рядом с приложением. К несчастью, это возможно только если приложение не
находится внутри пакета, так как в таком случае root_path указывает внутрь
пакета.
Во Flask 0.8 был введён новый атрибут: 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)
Путь к каталогу экземпляра может быть найден при помощи
Flask.instance_path
. Flask также предоставляет более короткий
способ открытия файлов из каталога экземпляра при помощи
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.