- en
- Language: ru
- Documentation version: 1.1.x
Обработка конфигурации¶
Приложения нуждаются в определенной конфигурации. Существуют различные настройки, которые вы можете изменить в зависимости от среды приложения, например, переключение режима отладки, установка секретного ключа и другие специфические для среды вещи.
Способ разработки Flask обычно требует, чтобы конфигурация была доступна при запуске приложения. Вы можете жестко прописать конфигурацию в коде, что для многих небольших приложений на самом деле не так уж плохо, но есть способы получше.
Независимо от способа загрузки конфигурации, существует объект config, в котором хранятся загруженные значения конфигурации: Атрибут config
объекта Flask
. Это место, куда сама Flask помещает определенные значения конфигурации, а также куда расширения могут помещать свои значения конфигурации. Но это также место, где вы можете иметь свою собственную конфигурацию.
Основы конфигурации¶
config
фактически является подклассом словаря и может быть изменен так же, как и любой другой словарь:
app = Flask(__name__)
app.config['TESTING'] = True
Определенные значения конфигурации также передаются в объект Flask
, чтобы вы могли читать и записывать их оттуда:
app.testing = True
Для одновременного обновления нескольких ключей можно использовать метод dict.update()
:
app.config.update(
TESTING=True,
SECRET_KEY=b'_5#y2L"F4Q8z\n\xec]/'
)
Функции среды и отладки¶
Значения конфигураций ENV
и DEBUG
являются особенными, поскольку они могут вести себя непоследовательно, если их изменить после начала настройки приложения. Чтобы надежно установить окружение и режим отладки, Flask использует переменные окружения.
Окружение используется для указания Flask, расширениям и другим программам, например Sentry, в каком контексте работает Flask. Оно управляется переменной окружения FLASK_ENV
и по умолчанию имеет значение production
.
Установка FLASK_ENV
в development
включит режим отладки. flask run
в режиме отладки по умолчанию будет использоваться интерактивный отладчик и перезагрузчик. Чтобы управлять этим отдельно от окружения, используйте флаг FLASK_DEBUG
.
Изменено в версии 1.0: Добавлено FLASK_ENV
для управления средой отдельно от режима отладки. Среда разработки включает режим отладки.
Чтобы переключить Flask в среду разработки и включить режим отладки, установите FLASK_ENV
:
$ export FLASK_ENV=development
$ flask run
(В Windows используйте set
вместо export
).
Рекомендуется использовать переменные окружения, как описано выше. Хотя можно установить ENV
и DEBUG
в вашем конфиге или коде, это настоятельно не рекомендуется. Они не могут быть прочитаны раньше командой flask
, а некоторые системы или расширения могут быть уже настроены на основе предыдущего значения.
Встроенные значения конфигурации¶
Следующие значения конфигурации используются внутри Flask:
- ENV¶
В какой среде работает приложение. Flask и расширения могут включать поведение, основанное на окружении, например, включать режим отладки. Атрибут
env
сопоставляется с этим ключом конфигурации. Он задается переменной окруженияFLASK_ENV
и может вести себя не так, как ожидается, если задан в коде.Не включайте разработку при развертывании в производстве..
По умолчанию:
'production'
Добавлено в версии 1.0.
- DEBUG¶
Включен ли режим отладки. При использовании
flask run
для запуска сервера разработки, интерактивный отладчик будет показан для необработанных исключений, и сервер будет перезагружен при изменении кода. Атрибутdebug
отображается на этот ключ конфигурации. Он включается, когдаENV
имеет значение'development'
и переопределяется переменной окруженияFLASK_DEBUG
. При установке в коде он может вести себя не так, как ожидается.Не включайте режим отладки при развертывании в производстве..
По умолчанию:
True
, еслиENV
равно'development'
, илиFalse
в противном случае.
- TESTING¶
Включите режим тестирования. Исключения распространяются, а не обрабатываются обработчиками ошибок приложения. Расширения также могут изменить свое поведение, чтобы облегчить тестирование. Вы должны включить этот режим в своих собственных тестах.
По умолчанию:
False
- PROPAGATE_EXCEPTIONS¶
Исключения перевызываются, а не обрабатываются обработчиками ошибок приложения. Если не задано, это неявно истинно, если включено
TESTING
илиDEBUG
.По умолчанию:
None
- PRESERVE_CONTEXT_ON_EXCEPTION¶
Не разворачивать контекст запроса при возникновении исключения. Если не задано, это значение будет истинным, если
DEBUG
истинно. Это позволяет отладчикам исследовать данные запроса при ошибках, и обычно не должно устанавливаться напрямую.По умолчанию:
None
- TRAP_HTTP_EXCEPTIONS¶
Если нет обработчика для исключения типа
HTTPException
, перевыразите его для обработки интерактивным отладчиком вместо того, чтобы возвращать его как простой ответ на ошибку.По умолчанию:
False
- TRAP_BAD_REQUEST_ERRORS¶
Попытка получить доступ к несуществующему ключу из массивов запросов типа
args
иform
приведет к возврату страницы с ошибкой 400 Bad Request. Включите эту опцию для обработки ошибки как необработанного исключения, чтобы получить интерактивный отладчик. Это более специфическая версияTRAP_HTTP_EXCEPTIONS
. Если параметр не установлен, он будет включен в режиме отладки.По умолчанию:
None
- SECRET_KEY¶
Секретный ключ, который будет использоваться для безопасной подписи сессионного cookie и может быть использован для любых других нужд, связанных с безопасностью, расширениями или вашим приложением. Это должна быть длинная случайная строка байтов, хотя юникод тоже принимается. Например, скопируйте этот вывод в свой config:
$ python -c 'import os; print(os.urandom(16))' b'_5#y2L"F4Q8z\n\xec]/'
Не раскрывайте секретный ключ при размещении вопросов или совершении кода..
По умолчанию:
None
- SESSION_COOKIE_NAME¶
Имя сессионного файла cookie. Может быть изменено в случае, если у вас уже есть cookie с таким же именем.
По умолчанию:
'session'
- SESSION_COOKIE_DOMAIN¶
Правило соответствия домена, для которого будет действовать сессионный файл cookie. Если не задано, cookie будет действительна для всех поддоменов
SERVER_NAME
. ЕслиFalse
, домен cookie не будет установлен.По умолчанию:
None
- SESSION_COOKIE_PATH¶
Путь, по которому будет действовать сессионный файл cookie. Если не задан, cookie будет действителен для пути
APPLICATION_ROOT
или/
, если он не задан.По умолчанию:
None
- SESSION_COOKIE_HTTPONLY¶
В целях безопасности браузеры не разрешают JavaScript доступ к файлам cookie, помеченным как «только HTTP».
По умолчанию:
True
- SESSION_COOKIE_SECURE¶
Браузеры будут отправлять куки с запросами через HTTPS, только если куки помечены как «безопасные». Чтобы это имело смысл, приложение должно обслуживаться через HTTPS.
По умолчанию:
False
- SESSION_COOKIE_SAMESITE¶
Ограничивает отправку файлов cookie при запросах с внешних сайтов. Может быть установлено значение
'Lax'
(рекомендуется) или'Strict'
. См. Параметры Set-Cookie.По умолчанию:
None
Добавлено в версии 1.0.
- PERMANENT_SESSION_LIFETIME¶
Если
session.permanent
равно true, то срок действия cookie будет установлен на это количество секунд вперед. Может быть либоdatetime.timedelta
, либоint
.Реализация cookie по умолчанию во Flask проверяет, что криптографическая подпись не старше этого значения.
По умолчанию:
timedelta(days=31)
(2678400
секунд)
- SESSION_REFRESH_EACH_REQUEST¶
Контролирует, отправляется ли cookie при каждом ответе, если значение
session.permanent
равно true. Отправка cookie каждый раз (по умолчанию) может более надежно удерживать сессию от истечения срока действия, но использует большую пропускную способность. Непостоянные сессии не затрагиваются.По умолчанию:
True
- USE_X_SENDFILE¶
При обслуживании файлов устанавливайте заголовок
X-Sendfile
вместо того, чтобы обслуживать данные с помощью Flask. Некоторые веб-серверы, такие как Apache, распознают это и обслуживают данные более эффективно. Это имеет смысл только при использовании такого сервера.По умолчанию:
False
- SEND_FILE_MAX_AGE_DEFAULT¶
При обслуживании файлов установите максимальный возраст управления кэшем на это число секунд. Может быть либо
datetime.timedelta
, либоint
. Переопределите это значение для каждого файла с помощьюget_send_file_max_age()
в приложении или чертеже.По умолчанию:
timedelta(hours=12)
(43200
секунд)
- SERVER_NAME¶
Сообщает приложению, к какому хосту и порту оно привязано. Требуется для поддержки поддоменного согласования маршрутов.
Если установлен, то будет использоваться для домена cookie сессии, если
SESSION_COOKIE_DOMAIN
не установлен. Современные веб-браузеры не позволяют устанавливать cookie для доменов без точки. Чтобы использовать домен локально, добавьте в файлhosts
все имена, которые должны направляться к приложению.127.0.0.1 localhost.dev
Если установлено,
url_for
может генерировать внешние URL, используя только контекст приложения вместо контекста запроса.По умолчанию:
None
- APPLICATION_ROOT¶
Сообщает приложению, по какому пути оно смонтировано приложением / веб-сервером. Это используется для генерации URL вне контекста запроса (внутри запроса диспетчер отвечает за установку
SCRIPT_NAME
вместо этого; примеры конфигурации диспетчера см. в Application Dispatching).Будет использоваться для пути к cookie сессии, если
SESSION_COOKIE_PATH
не установлен.По умолчанию:
'/'
- PREFERRED_URL_SCHEME¶
Используйте эту схему для генерации внешних URL-адресов, когда они не находятся в контексте запроса.
По умолчанию:
'http'
- MAX_CONTENT_LENGTH¶
Не считывать больше этого количества байт из входящих данных запроса. Если не установлено и в запросе не указано
CONTENT_LENGTH
, данные не будут считываться для безопасности.По умолчанию:
None
- JSON_AS_ASCII¶
Сериализация объектов в JSON в ASCII-кодировке. Если эта функция отключена, JSON будет возвращаться в виде строки Unicode или в кодировке
UTF-8
отjsonify
. Это имеет последствия для безопасности при преобразовании JSON в JavaScript в шаблонах, и обычно должно оставаться включенным.По умолчанию:
True
- JSON_SORT_KEYS¶
Сортировка ключей объектов JSON в алфавитном порядке. Это полезно для кэширования, поскольку гарантирует, что данные будут сериализованы одинаково, независимо от того, каково семя хэша в Python. Хотя это не рекомендуется, вы можете отключить эту функцию для возможного повышения производительности за счет кэширования.
По умолчанию:
True
- JSONIFY_PRETTYPRINT_REGULAR¶
jsonify
ответы будут выводиться с новыми строками, пробелами и отступами для более удобного чтения человеком. Всегда включается в режиме отладки.По умолчанию:
False
- JSONIFY_MIMETYPE¶
Тип mimetype ответов
jsonify
.По умолчанию:
'application/json'
- TEMPLATES_AUTO_RELOAD¶
Перезагружать шаблоны при их изменении. Если не установлен, то будет включен в режиме отладки.
По умолчанию:
None
- EXPLAIN_TEMPLATE_LOADING¶
Запись в журнал отладочной информации, отслеживающей, как был загружен файл шаблона. Это может быть полезно для выяснения того, почему шаблон не загружается или загружается не тот файл.
По умолчанию:
False
- MAX_COOKIE_SIZE¶
Предупреждать, если размер заголовков cookie превышает указанное количество байт. По умолчанию установлено значение
4093
. Файлы cookie большего размера могут молча игнорироваться браузерами. Установите значение0
, чтобы отключить предупреждение.
Добавлено в версии 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
Добавлено в версии 0.11: SESSION_REFRESH_EACH_REQUEST
, TEMPLATES_AUTO_RELOAD
,
LOGGER_HANDLER_POLICY
, EXPLAIN_TEMPLATE_LOADING
Изменено в версии 1.0: LOGGER_NAME
и LOGGER_HANDLER_POLICY
были удалены. Информацию о конфигурации смотрите в Ведение журнала.
Добавлена ENV
для отражения переменной окружения FLASK_ENV
.
Добавлено SESSION_COOKIE_SAMESITE
для управления параметром SameSite
сессионного cookie.
Добавлено MAX_COOKIE_SIZE
для управления предупреждением от Werkzeug.
Конфигурирование из файлов¶
Конфигурация становится более полезной, если вы можете хранить ее в отдельном файле, в идеале расположенном вне пакета приложения. Это делает возможным упаковку и распространение приложения с помощью различных инструментов обработки пакетов (Развертывание с помощью инструментов Setuptools) и, наконец, последующее изменение конфигурационного файла.
Итак, общая схема такова:
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. В дальнейшем в объекте config будут храниться только значения в верхнем регистре. Поэтому обязательно используйте заглавные буквы для ключей конфигурации.
Вот пример конфигурационного файла:
# Example configuration
DEBUG = False
SECRET_KEY = b'_5#y2L"F4Q8z\n\xec]/'
Обязательно загрузите конфигурацию на самом раннем этапе, чтобы расширения имели возможность доступа к ней при запуске. Существуют и другие методы объекта config для загрузки из отдельных файлов. Для получения полной информации прочтите документацию объекта Config
.
Настройка из переменных среды¶
В дополнение к указанию на конфигурационные файлы с помощью переменных среды, вы можете счесть полезным (или необходимым) управлять значениями конфигурации непосредственно из среды.
Переменные окружения можно установить в Linux или OS X с помощью команды export в оболочке перед запуском сервера:
$ export SECRET_KEY='5f352379324c22463451387a0aec5d2f'
$ export MAIL_ENABLED=false
$ python run-app.py
* Running on http://127.0.0.1:5000/
В системах Windows вместо этого используйте встроенную функцию set
:
> set SECRET_KEY='5f352379324c22463451387a0aec5d2f'
Хотя этот подход прост в использовании, важно помнить, что переменные окружения являются строками - они не десериализуются автоматически в типы Python.
Вот пример конфигурационного файла, в котором используются переменные среды:
import os
_mail_enabled = os.environ.get("MAIL_ENABLED", default="true")
MAIL_ENABLED = _mail_enabled.lower() in {"1", "t", "true"}
SECRET_KEY = os.environ.get("SECRET_KEY")
if not SECRET_KEY:
raise ValueError("No SECRET_KEY set for Flask application")
Обратите внимание, что любое значение, кроме пустой строки, будет интерпретироваться в Python как булево значение True
, что требует осторожности, если среда явно устанавливает значения, предназначенные для False
.
Обязательно загрузите конфигурацию на самом раннем этапе, чтобы расширения имели возможность доступа к ней при запуске. Существуют и другие методы объекта config для загрузки из отдельных файлов. Для получения полной информации ознакомьтесь с документацией класса Config
.
Лучшие практики конфигурирования¶
Недостатком упомянутого выше подхода является то, что он делает тестирование немного сложнее. Не существует единого 100% решения этой проблемы в целом, но есть несколько вещей, которые можно иметь в виду, чтобы улучшить этот опыт:
Создайте свое приложение в функции и зарегистрируйте на нем чертежи. Таким образом, вы можете создать несколько экземпляров приложения с разными конфигурациями, что значительно упрощает модульное тестирование. Вы можете использовать это для передачи конфигурации по мере необходимости.
Не пишите код, которому нужна конфигурация во время импорта. Если вы ограничитесь доступом к конфигурации только по запросу, вы сможете переконфигурировать объект позже по мере необходимости.
Разработка / Производство¶
Большинству приложений требуется более одной конфигурации. Должны быть как минимум отдельные конфигурации для рабочего сервера и сервера, используемого во время разработки. Самый простой способ справиться с этим - использовать конфигурацию по умолчанию, которая всегда загружена и является частью контроля версий, и отдельную конфигурацию, которая переопределяет значения по мере необходимости, как указано в примере выше:
app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')
Тогда вам просто нужно добавить отдельный файл config.py
и экспортировать 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')
Обратите внимание, что from_object()
не инстанцирует объект класса. Если вам необходимо инстанцировать класс, например, для доступа к свойству, то вы должны сделать это до вызова from_object()
:
from configmodule import ProductionConfig
app.config.from_object(ProductionConfig())
# Alternatively, import via string:
from werkzeug.utils import import_string
cfg = import_string('configmodule.ProductionConfig')()
app.config.from_object(cfg)
Инстанцирование объекта конфигурации позволяет вам использовать @property
в ваших классах конфигурации:
class Config(object):
"""Base config, uses staging database server."""
DEBUG = False
TESTING = False
DB_SERVER = '192.168.1.56'
@property
def DATABASE_URI(self): # Note: all caps
return 'mysql://user@{}/foo'.format(self.DB_SERVER)
class ProductionConfig(Config):
"""Uses production database server."""
DB_SERVER = '192.168.19.32'
class DevelopmentConfig(Config):
DB_SERVER = 'localhost'
DEBUG = True
class TestingConfig(Config):
DB_SERVER = 'localhost'
DEBUG = True
DATABASE_URI = 'sqlite:///:memory:'
Существует множество различных способов, и вы сами решаете, как управлять своими конфигурационными файлами. Однако здесь приведен список хороших рекомендаций:
Храните конфигурацию по умолчанию в системе контроля версий. Либо заполните конфигурацию этой конфигурацией по умолчанию, либо импортируйте ее в свои собственные конфигурационные файлы, прежде чем переопределять значения.
Используйте переменную окружения для переключения между конфигурациями. Это может быть сделано вне интерпретатора Python и значительно упрощает разработку и развертывание, поскольку вы можете быстро и легко переключаться между различными конфигурациями, не касаясь кода. Если вы часто работаете над разными проектами, вы даже можете создать собственный скрипт для сорсинга, который активирует virtualenv и экспортирует конфигурацию разработки для вас.
Используйте такой инструмент, как fabric в продакшене для отдельной отправки кода и конфигураций на продакшен-сервер(ы). Для получения подробной информации о том, как это сделать, перейдите к шаблону Развертывание с помощью Fabric.
Папки экземпляров¶
Добавлено в версии 0.8.
Flask 0.8 вводит папки экземпляров. Долгое время Flask позволял ссылаться на пути относительно папки приложения напрямую (через Flask.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
, чтобы узнать, какой префикс установлен.
Поскольку объект config обеспечивает загрузку конфигурационных файлов из относительных имен файлов, мы сделали возможным изменить загрузку через имена файлов на относительную к пути экземпляра, если это необходимо. Поведение относительных путей в конфигурационных файлах может быть изменено с «относительно корня приложения» (по умолчанию) на «относительно папки экземпляра» с помощью переключателя 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()
# or via open_instance_resource:
with app.open_instance_resource('application.cfg') as f:
config = f.read()