Обработка конфигурации
Приложениям требуется некоторая конфигурация. Есть разные параметры, которые вы можете изменить в зависимости от среды приложения, например, включить режим отладки, установить секретный ключ и другие специфичные для среды вещи.
Дизайн Flask обычно требует, чтобы конфигурация была доступна при запуске приложения. Вы можете жёстко закодировать конфигурацию в коде, что для многих небольших приложений не так уж и плохо, но существуют лучшие способы.
Независимо от того, как вы загружаете свою конфигурацию, доступен объект конфигурации, который хранит загруженные значения конфигурации: атрибут config объекта Flask. В нём Flask сам размещает определённые значения конфигурации, а также расширения могут помещать свои значения конфигурации. Но здесь также вы можете иметь собственную конфигурацию.
Основы конфигурации
Атрибут config фактически является подклассом словаря и может быть изменён как любой словарь:
app = Flask(__name__) app.config['TESTING'] = True
Некоторые значения конфигурации также передаются объекту Flask, поэтому вы можете читать и записывать их оттуда:
app.testing = True
Чтобы обновить сразу несколько ключей, вы можете использовать метод dict.update():
app.config.update(
TESTING=True,
SECRET_KEY='192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
)
Режим отладки
Значение конфигурации DEBUG является специальным, потому что оно может вести себя непредсказуемо, если его изменить после того, как приложение начало настраиваться. Чтобы надёжно установить режим отладки, используйте опцию --debug в команде flask. ``flask run`` по умолчанию будет использовать интерактивный отладчик и перезагрузчик в режиме отладки.
$ flask --app hello --debug run
Использование опции рекомендуется. Хотя можно установить DEBUG в вашей конфигурации или коде, это крайне не рекомендуется. Его нельзя прочитать заранее командой flask , и некоторые системы или расширения могут уже настроиться на основе предыдущего значения.
Встроенные значения конфигурации
Следующие значения конфигурации используются во Flask:
-
ENV -
В какой среде приложение запущено. Атрибут
envсопоставлен с этим ключом конфигурации.По умолчанию:
'production'Устарело начиная с версии 2.2: Будет удалено в Flask 2.3. Используйте
--debugвместо этого.Журнал изменений
Добавлена в версии 1.0.
-
DEBUG -
Включен ли режим отладки. При использовании
flask runдля запуска сервера разработки, при возникновении необработанных исключений будет показан интерактивный отладчик, а сервер будет перезапущен при изменении кода. Атрибутdebugсопоставлен с этим ключом конфигурации. Это устанавливается с помощью переменной окруженияFLASK_DEBUG. Возможно, он не будет работать так, как ожидается, если установлен в коде.Не включайте режим отладки при развертывании в продакшене.
По умолчанию:
False
-
TESTING -
Включить режим тестирования. Исключение передаются без обработки обработчиками ошибок приложения. Расширения также могут изменить своё поведение для облегчения тестирования. Вам следует включить это в собственных тестах.
По умолчанию:
False
-
PROPAGATE_EXCEPTIONS -
Исключения перевыбрасываются, вместо того чтобы обрабатываться обработчиками ошибок приложения. Если не задано, это подразумевается, если
TESTINGилиDEBUGвключены.По умолчанию:
None
-
TRAP_HTTP_EXCEPTIONS -
Если нет обработчика для исключения типа
HTTPException, он перевыбрасывается для обработки интерактивным отладчиком, а не возвращается как простое сообщение об ошибке.По умолчанию:
False
-
TRAP_BAD_REQUEST_ERRORS -
Попытка получить ключ, которого нет в словарях запроса, таких как
argsиform, вернёт ошибку 400 Bad Request. Включите это, чтобы рассматривать ошибку как необработанное исключение, чтобы получить интерактивный отладчик. Это более конкретная версияTRAP_HTTP_EXCEPTIONS. Если не установлено, включено в режиме отладки.По умолчанию:
None
-
SECRET_KEY -
Секретный ключ, который используется для безопасного шифрования куки сессии и может быть использован для любых других задач безопасности расширениями или вашим приложением. Он должен быть длинным случайным
bytesилиstr. Например, скопируйте вывод этого в вашу конфигурацию:$ python -c 'import secrets; print(secrets.token_hex())' '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
Не раскрывайте секретный ключ, когда публикуете вопросы или коммитите код.
По умолчанию:
None
-
SESSION_COOKIE_NAME -
Название куки сессии. Можно изменить, если у вас уже есть куки с таким же именем.
По умолчанию:
'session'
-
SESSION_COOKIE_DOMAIN -
Правило соответствия домена, для которого куки сессии будет действительным. Если не указано, куки будет действительным для всех поддоменов
SERVER_NAME. ЕслиFalse, домен куки не будет установлен.По умолчанию:
None
-
SESSION_COOKIE_PATH -
Путь, для которого куки сессии будет действительным. Если не указано, куки будет действителен внутри
APPLICATION_ROOTили/если это не задано.По умолчанию:
None
-
SESSION_COOKIE_HTTPONLY -
Браузеры не позволят JavaScript получить доступ к кукам, помеченным как «только HTTP», для безопасности.
По умолчанию:
True
-
SESSION_COOKIE_SECURE -
Браузеры будут отправлять куки только с запросами через HTTPS, если куки помечены как «защищённые». Приложение должно обслуживаться через HTTPS, чтобы это имело смысл.
По умолчанию:
False
-
SESSION_COOKIE_SAMESITE -
Ограничение того, как куки отправляются с запросами с внешних сайтов. Можно установить в
'Lax'(рекомендуется) или'Strict'. См. Параметры Set-Cookie.По умолчанию:
NoneЖурнал изменений
Добавлена в версии 1.0.
-
PERMANENT_SESSION_LIFETIME -
Если
session.permanentравно true, срок действия куки будет установлен на это число секунд в будущем. Может быть либоdatetime.timedelta, либоint.Встроенная реализация куки Flask проверяет, что криптографическая подпись не старше этого значения.
По умолчанию:
timedelta(days=31)(2678400секунд)
-
SESSION_REFRESH_EACH_REQUEST -
Управление тем, отправляется ли куки с каждым ответом, когда
session.permanentравно true. Отправка куки каждый раз (по умолчанию) более надёжно предотвращает истечение сессии, но использует больше пропускной способности. Непостоянные сессии не затрагиваются.По умолчанию:
True
-
USE_X_SENDFILE -
При обслуживании файлов задайте заголовок
X-Sendfileвместо передачи данных с помощью Flask. Некоторые веб-серверы, такие как Apache, распознают это и передают данные более эффективно. Это имеет смысл только при использовании такого сервера.По умолчанию:
False
-
SEND_FILE_MAX_AGE_DEFAULT -
При обслуживании файлов задайте максимальное время кэширования по контролю кэша на это количество секунд. Может быть
datetime.timedeltaилиint. Переопределяйте это значение для каждого файла, используяget_send_file_max_age()в приложении или бланке.Если
None,send_fileуказывает браузеру использовать условные запросы вместо кэширования по таймеру, что обычно предпочтительнее.По умолчанию:
None
-
SERVER_NAME -
Укажите приложению хост и порт, к которому оно привязано. Требуется для поддержки сопоставления маршрутов по поддоменам.
Если установлено, будет использоваться для домена куки сессии, если
SESSION_COOKIE_DOMAINне задано. Современные веб-браузеры не разрешают устанавливать куки для доменов без точки. Чтобы использовать домен локально, добавьте все имена, которые должны перенаправляться в приложение, в свой файлhosts.127.0.0.1 localhost.dev
Если установлено,
url_forможет генерировать внешние URL-адреса только с контекстом приложения, а не контекстом запроса.По умолчанию:
None
-
APPLICATION_ROOT -
Укажите приложению, под какой путь оно смонтировано приложением/веб-сервером. Это используется для генерации URL-адресов вне контекста запроса (внутри запроса, диспетчер отвечает за установку
SCRIPT_NAMEвместо этого; см. Диспечеризация приложений для примеров конфигурации диспетчеризации).Будет использоваться для пути куки сессии, если
SESSION_COOKIE_PATHне установлен.По умолчанию:
'/'
-
PREFERRED_URL_SCHEME -
Используйте эту схему для генерации внешних URL-адресов, когда нет контекста запроса.
По умолчанию:
'http'
-
MAX_CONTENT_LENGTH -
Не читайте более этого количества байтов из данных входящего запроса. Если не установлено и запрос не указывает
CONTENT_LENGTH, данные не будут считываться для безопасности.По умолчанию:
None
-
JSON_AS_ASCII -
Сериализуйте объекты в JSON с кодировкой ASCII. Если это отключено, JSON, возвращаемый из
jsonify, будет содержать символы Юникода. Это имеет последствия для безопасности при рендеринге JSON в JavaScript в шаблонах и, как правило, должно оставаться включённым.По умолчанию:
TrueУстарело начиная с версии 2.2: Будет удалено в Flask 2.3. Задайте
app.json.ensure_asciiвместо этого.
-
JSON_SORT_KEYS -
Сортировать ключи JSON-объектов в алфавитном порядке. Это полезно для кеширования, потому что гарантирует, что данные сериализуются одинаково независимо от того, что у Python за seed хеша. Не рекомендуется, но вы можете отключить его для возможного повышения производительности ценой кеширования.
По умолчанию:
TrueУстарело начиная с версии 2.2: Будет удалено в Flask 2.3. Задайте
app.json.sort_keysвместо этого.
-
JSONIFY_PRETTYPRINT_REGULAR -
Ответы будут выводиться с новой строкой, пробелами и отступами для лучшего восприятия человеком. Всегда включено в режиме отладки.
По умолчанию:
FalseУстаревшее начиная с версии 2.2: Будет удалено в Flask 2.3. Установите
app.json.compactвместо этого.
-
JSONIFY_MIMETYPE -
Тип MIME ответов
jsonify.По умолчанию:
'application/json'Устаревшее начиная с версии 2.2: Будет удалено в Flask 2.3. Установите
app.json.mimetypeвместо этого.
-
TEMPLATES_AUTO_RELOAD -
Перезагружать шаблоны при их изменении. Если не задано, включено в режиме отладки.
По умолчанию:
None
-
EXPLAIN_TEMPLATE_LOADING -
Записывать отладочную информацию о том, как загружается файл шаблона. Это может быть полезно для выяснения причин, по которым шаблон не был загружен или загружен неверный файл.
По умолчанию:
False
-
MAX_COOKIE_SIZE -
Выводить предупреждение, если заголовки cookie превышают это количество байтов. По умолчанию
4093. Браузеры могут игнорировать более крупные cookie. Установите значение0для отключения предупреждения.
Изменено в версии 2.2: Убрано PRESERVE_CONTEXT_ON_EXCEPTION.
Изменено в версии 2.2: JSON_AS_ASCII, JSON_SORT_KEYS, JSONIFY_MIMETYPE, и JSONIFY_PRETTYPRINT_REGULAR будут удалены в Flask 2.3. У поставщика по умолчанию app.json есть эквивалентные атрибуты.
Изменено в версии 2.2: ENV будет удалено в Flask 2.3. Используйте --debug вместо этого.
Журнал изменений
Изменено в версии 1.0: LOGGER_NAME и LOGGER_HANDLER_POLICY были удалены. Обратитесь к Ведению журнала за дополнительной информацией о настройке.
Добавлен ENV для отражения переменной окружения FLASK_ENV.
Добавлен SESSION_COOKIE_SAMESITE для управления опцией SameSite cookie сессии.
Добавлен MAX_COOKIE_SIZE для управления предупреждением из Werkzeug.
Добавлено в версии 0.11: SESSION_REFRESH_EACH_REQUEST, TEMPLATES_AUTO_RELOAD, LOGGER_HANDLER_POLICY, EXPLAIN_TEMPLATE_LOADING
Добавлено в версии 0.10: JSON_AS_ASCII, JSON_SORT_KEYS, JSONIFY_PRETTYPRINT_REGULAR
Добавлено в версии 0.9: PREFERRED_URL_SCHEME
Добавлено в версии 0.8: TRAP_BAD_REQUEST_ERRORS, TRAP_HTTP_EXCEPTIONS, APPLICATION_ROOT, SESSION_COOKIE_DOMAIN, SESSION_COOKIE_PATH, SESSION_COOKIE_HTTPONLY, SESSION_COOKIE_SECURE
Добавлено в версии 0.7: PROPAGATE_EXCEPTIONS, PRESERVE_CONTEXT_ON_EXCEPTION
Добавлено в версии 0.6: MAX_CONTENT_LENGTH
Добавлено в версии 0.5: SERVER_NAME
Добавлено в версии 0.4: LOGGER_NAME
Настройка из Python-файлов
Настройка становится более полезной, если вы можете хранить её в отдельном файле, предпочтительно вне самого пакета приложения. Вы можете развернуть своё приложение, а затем отдельно настроить его для конкретного развертывания.
Общий шаблон такой:
app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')
Это сначала загружает настройки из модуля yourapplication.default_settings и затем перезаписывает значения содержимым файла, на который указывает переменная окружения YOURAPPLICATION_SETTINGS. Эту переменную окружения можно установить в командной строке перед запуском сервера:
$ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg $ flask run * Running on http://127.0.0.1:5000/
$ set -x YOURAPPLICATION_SETTINGS /path/to/settings.cfg $ flask run * Running on http://127.0.0.1:5000/
> set YOURAPPLICATION_SETTINGS=\path\to\settings.cfg > flask run * Running on http://127.0.0.1:5000/
> $env:YOURAPPLICATION_SETTINGS = "\path\to\settings.cfg" > flask run * Running on http://127.0.0.1:5000/
Файлы конфигурации сами являются файлами Python. Только значения в верхнем регистре фактически сохраняются в объекте конфигурации позже. Поэтому убедитесь, что для ваших ключей конфигурации используются заглавные буквы.
Вот пример файла конфигурации:
# Example configuration SECRET_KEY = '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
Убедитесь, что вы загружаете конфигурацию очень рано, чтобы расширения могли получить доступ к конфигурации при запуске. В объекте конфигурации есть и другие методы для загрузки из отдельных файлов. Для получения полной справки, прочитайте документацию к объекту Config.
Настройка из файлов данных
Также можно загрузить конфигурацию из файла в формате по вашему выбору, используя from_file(). Например, для загрузки из файла TOML:
import toml
app.config.from_file("config.toml", load=toml.load)
Или из файла JSON:
import json
app.config.from_file("config.json", load=json.load)
Настройка из переменных среды
Помимо указания на конфигурационные файлы с помощью переменных среды, вам может быть полезно (или необходимо) управлять значениями конфигурации непосредственно из среды. Flask можно настроить на загрузку всех переменных среды, начинающихся со специфического префикса, в конфигурацию с помощью from_prefixed_env().
Переменные среды можно задать в оболочке перед запуском сервера:
$ export FLASK_SECRET_KEY="5f352379324c22463451387a0aec5d2f" $ export FLASK_MAIL_ENABLED=false $ flask run * Running on http://127.0.0.1:5000/
$ set -x FLASK_SECRET_KEY "5f352379324c22463451387a0aec5d2f" $ set -x FLASK_MAIL_ENABLED false $ flask run * Running on http://127.0.0.1:5000/
> set FLASK_SECRET_KEY="5f352379324c22463451387a0aec5d2f" > set FLASK_MAIL_ENABLED=false > flask run * Running on http://127.0.0.1:5000/
> $env:FLASK_SECRET_KEY = "5f352379324c22463451387a0aec5d2f" > $env:FLASK_MAIL_ENABLED = "false" > flask run * Running on http://127.0.0.1:5000/
Переменные затем можно загрузить и получить доступ к ним через конфигурацию с ключом, равным имени переменной среды без префикса, т.е.
app.config.from_prefixed_env() app.config["SECRET_KEY"] # Is "5f352379324c22463451387a0aec5d2f"
Префикс по умолчанию FLASK_. Это настраивается через аргумент prefix метода from_prefixed_env().
Значения будут анализироваться для попытки преобразования их в тип, более конкретный, чем строки. По умолчанию используется json.loads(), поэтому возможны любые допустимые значения JSON, включая списки и словари. Это настраивается через аргумент loads метода from_prefixed_env().
При добавлении булевого значения с помощью анализа JSON по умолчанию только «true» и «false», в нижнем регистре, являются допустимыми значениями. Имейте в виду, что любая непустая строка считается True в Python.
Можно задавать ключи вложенных словарей, разделяя ключи двойным подчеркиванием (__). Любые промежуточные ключи, которые отсутствуют в родительском словаре, будут инициализированы пустым словарем.
$ export FLASK_MYAPI__credentials__username=user123
app.config["MYAPI"]["credentials"]["username"] # Is "user123"
В Windows ключи переменных среды всегда записываются заглавными буквами, поэтому вышеприведенный пример приведет к MYAPI__CREDENTIALS__USERNAME.
Для ещё большего набора возможностей загрузки конфигурации, включая слияние и поддержку регистронезависимых имен в Windows, попробуйте специальную библиотеку, такую как Dynaconf, которая включает интеграцию с Flask.
Рекомендации по лучшим практикам конфигурации
Недостатком ранее упомянутого подхода является то, что он усложняет тестирование. Нет универсального решения этой проблемы, но есть несколько моментов, которые следует учитывать для повышения удобства:
- Создайте приложение в функции и зарегистрируйте в ней схемы. Таким образом, вы можете создавать несколько экземпляров приложения с различными прикреплёнными конфигурациями, что значительно упрощает unit-тестирование. Вы можете использовать это для передачи необходимой конфигурации.
- Не пишите код, которому требуется конфигурация во время импорта. Если ограничиться только доступом к конфигурации при запросе, вы можете переконфигурировать объект по мере необходимости.
- Убедитесь, что конфигурация загружается на очень ранней стадии, чтобы расширения могли получить доступ к конфигурации при вызове
init_app.
Разработка / Производство
Большинству приложений требуется более одной конфигурации. Должны быть, по крайней мере, отдельные конфигурации для сервера производства и сервера разработки. Самый простой способ решения этой задачи — использовать стандартную конфигурацию, которая всегда загружается и является частью системы контроля версий, а отдельные конфигурации переопределяют значения по мере необходимости, как показано в примере выше:
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):
TESTING = False
class ProductionConfig(Config):
DATABASE_URI = 'mysql://user@localhost/foo'
class DevelopmentConfig(Config):
DATABASE_URI = "sqlite:////tmp/foo.db"
class TestingConfig(Config):
DATABASE_URI = 'sqlite:///:memory:'
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."""
TESTING = False
DB_SERVER = '192.168.1.56'
@property
def DATABASE_URI(self): # Note: all caps
return f"mysql://user@{self.DB_SERVER}/foo"
class ProductionConfig(Config):
"""Uses production database server."""
DB_SERVER = '192.168.19.32'
class DevelopmentConfig(Config):
DB_SERVER = 'localhost'
class TestingConfig(Config):
DB_SERVER = 'localhost'
DATABASE_URI = 'sqlite:///:memory:'
Существует множество различных способов, и как вы хотите управлять своими файлами конфигурации — дело ваше. Однако вот список хороших рекомендаций:
- Храните стандартную конфигурацию в системе контроля версий. Либо заполните конфигурацию этой стандартной конфигурацией, либо импортируйте её в собственные файлы конфигурации перед переопределением значений.
- Используйте переменную среды для переключения между конфигурациями. Это можно сделать вне интерпретатора Python и значительно упростит разработку и развертывание, так как вы сможете быстро и легко переключаться между разными конфигурациями, не изменяя код. Если вы работаете часто над разными проектами, вы можете даже создать собственную скрипт для подготовки, который активирует виртуальную среду и экспортирует для вас конфигурацию разработки.
- Используйте инструмент, такой как 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/pythonX.Y/site-packages/myapp $PREFIX/var/myapp-instance
$PREFIX— префикс вашей установки Python. Это может быть/usrили путь к вашей виртуальной среде. Вы можете вывести значение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()
# or via open_instance_resource:
with app.open_instance_resource('application.cfg') as f:
config = f.read()
© 2007–2022 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.2.x/config/