Новинка версии 0.3
Приложения требуют настройки. Здесь описаны различные настройки, которые можно менять в зависимости от окружения, в котором работает приложение: переключение режима отладки, настройки секретного ключа и т.п.
Flask спроектирован так, что обычно требует настройки при запуске приложения. Вы можете вшить настройки в код, что не так уж плохо для многих небольших приложений, но имеются способы лучше.
Вне зависимости от того, каким образом загружена конфигурация, существует объект конфигурации, содержащий загруженные параметры: атрибут config объекта Flask. Это место, где Flask содержит свои настройки, а также то место, куда расширения могут поместить собственные настройки. Но здесь можно размещать и конфигурацию вашего приложения.
Основы конфигурации
config на самом деле является подклассом словаря и может изменяться точно так же, как и любой словарь:
app = Flask(__name__) app.config['DEBUG'] = TrueНекоторые параметры конфигурации передаются в объект Flask, которые тоже можно читать и писать:
app.debug = TrueДля обновления нескольких ключей за раз можно воспользоваться методом словаря 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 (что защищает переменную от доступа со стороны скриптов, работающих внутри браузера - прим. перев.). По умолчанию - истина. |
SESSION_COOKIE_SECURE | Указывает, должен ли у переменной браузера устанавливаться флаг secure (что позволяет передавать переменную только по защищённому протоколу HTTPS - прим. перев.). По умолчанию - ложь. |
PERMANENT_SESSION_LIFETIME | Непрерывное время жизни сеанса, как объект 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 | По умолчанию задаёт время кэширования файла для использования совместно с send_static_file() (обработчик статических файлов по умолчанию) и send_file(), в секундах. Заменить это значение для каждого файла индивидуально можно с помощью обработчика get_send_file_max_age() Flask или Blueprint. По умолчанию - 43200 (12 часов). |
TRAP_HTTP_EXCEPTIONS | Если истина, Flask не выполняет обработчиков ошибок исключений HTTP, но вместо этого трактует исключение как любое другое и передаёт исключение выше. Этот параметр полезен для отладки сложных случаев, когда нужно найти, где именно произошло исключение HTTP. |
TRAP_BAD_REQUEST_ERRORS | Внутренние структуры данных Werkzeug, работающие с данными запроса порождают ошибки с особым ключом, также являющимся исключением запроса. Также, многие операции могут неявно приводить к исключениям BadRequest в случае ошибок целостности. Поскольку для отладки важно знать, где именно произошла ошибка, этот флаг может использоваться для отладки в подобных случаях. Если этот параметр истинен, произойдёт обычная выдача результата трассировки. |
PREFERRED_URL_SCHEME | Схема, которую нужно использовать для генерации URL'ов, если она не указана явно. По умолчанию - http. |
Подробнее о 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
Задание конфигурации с помощью файлов
Конфигурация становится более удобной, если разместить её в отдельном файле. Лучше, если он находится за пределами пакета с приложением. Это позволяет создавать пакеты и распространять приложения с помощью различных инструментов обработки пакетов (Развёртывание приложений при помощи distribute) и впоследствии - изменять конфигурацию.
Далее показан обычный пример:
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.
Новинка версии 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, чтобы увидеть его действительное значение.
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.
Примечания переводчика
Этот и другие переводы можно найти на сайте проекта перевода документации по Flask. Автор проекта - Виталий Кузьмин aka ferm32.
Комментариев нет:
Отправить комментарий