Spec-Zone.ru › Flask 2.3

Обработка конфигурации

Приложениям необходима некая конфигурация. Есть различные настройки, которые вы можете изменить в зависимости от среды приложения, например, включение режима отладки, установка секретного ключа и другие специфичные для среды вещи.

Способ реализации 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='192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
)

Режим отладки

Значение конфигурации DEBUG является специальным, поскольку его поведение может быть непредсказуемым, если его изменить после начала настройки приложения. Для надёжной установки режима отладки используйте опцию --debug в команде flask или flask run. flask run будет использовать интерактивный отладчик и релоадер по умолчанию в режиме отладки.

$ flask --app hello run --debug

Рекомендуется использовать эту опцию. Хотя можно установить DEBUG в вашей конфигурации или коде, это настоятельно не рекомендуется. Его нельзя прочитать до команды flask run, и некоторые системы или расширения могут уже настроить себя на основе предыдущего значения.

Встроенные значения конфигурации

Следующие значения конфигурации используются внутри Flask:

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

Секретный ключ, который будет использоваться для безопасного подписывания cookie сессии и может быть использован для любых других задач безопасности расширениями или вашим приложением. Должен быть длинным случайным bytes или str. Например, скопируйте вывод этого в вашу конфигурацию:

$ python -c 'import secrets; print(secrets.token_hex())'
'192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'

Не раскрывайте секретный ключ при публикации вопросов или коммитах кода.

По умолчанию: None

SESSION_COOKIE_NAME

Имя cookie сессии. Можно изменить, если у вас уже есть cookie с таким же именем.

По умолчанию: 'session'

SESSION_COOKIE_DOMAIN

Значение параметра Domain для cookie сессии. Если не установлено, браузеры будут отправлять cookie только на точный домен, из которого он был установлен. В противном случае они будут отправлять его и на любые поддомены заданного значения.

Не установление этого значения более ограниченно и безопасно, чем его установка.

По умолчанию: None

Изменено в версии 2.3: Не установлено по умолчанию, не использует SERVER_NAME по умолчанию.

SESSION_COOKIE_PATH

Путь, для которого будет действительна cookie сессии. Если не установлено, cookie будет действителен в рамках APPLICATION_ROOT или /, если это не задано.

По умолчанию: None

SESSION_COOKIE_HTTPONLY

Браузеры не позволят JavaScript получить доступ к cookie, помеченным как «только HTTP», для обеспечения безопасности.

По умолчанию: True

SESSION_COOKIE_SECURE

Браузеры будут отправлять cookie только с запросами по протоколу HTTPS, если для cookie установлено значение «secure». Приложение должно обслуживаться через 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() в приложении или модуле.

Если None, send_file указывает браузеру использовать условные запросы вместо кэширования по времени, что обычно предпочтительнее.

По умолчанию: None

SERVER_NAME

Сообщить приложению о том, к какому хосту и порту оно привязано. Необходимо для поддержки сопоставления маршрутов по поддоменам.

Если установлено, url_for может генерировать внешние URL-адреса только с контекстом приложения вместо контекста запроса.

По умолчанию: None

Изменено в версии 2.3: Не влияет на SESSION_COOKIE_DOMAIN.

APPLICATION_ROOT

Указать приложению путь, под которым оно смонтировано приложением/веб-сервером. Это используется для генерации URL-адресов за пределами контекста запроса (внутри запроса, диспетчер отвечает за установку SCRIPT_NAME вместо этого; см. Перенаправление приложения для примеров конфигурации перенаправления).

Будет использоваться для пути cookie сессии, если SESSION_COOKIE_PATH не задан.

По умолчанию: '/'

PREFERRED_URL_SCHEME

Используйте эту схему для генерации внешних URL-адресов, когда нет контекста запроса.

По умолчанию: 'http'

MAX_CONTENT_LENGTH

Не читать больше этого количества байтов из входящих данных запроса. Если не задано и запрос не указывает CONTENT_LENGTH, данные не будут читаться по соображениям безопасности.

По умолчанию: None

TEMPLATES_AUTO_RELOAD

Перезагружать шаблоны при их изменении. Если не задано, оно будет включено в режиме отладки.

По умолчанию: None

EXPLAIN_TEMPLATE_LOADING

Вести журнал отладочной информации, отслеживающей, как был загружен файл шаблона. Это может быть полезно, чтобы понять, почему шаблон не был загружен или загружен неверный файл.

По умолчанию: False

MAX_COOKIE_SIZE

Вывести предупреждение, если заголовки cookie превышают это количество байт. По умолчанию 4093. Большие cookie могут быть проигнорированы браузерами. Установите 0 для отключения предупреждения.

Изменено в версии 2.3: JSON_AS_ASCII, JSON_SORT_KEYS, JSONIFY_MIMETYPE, и JSONIFY_PRETTYPRINT_REGULAR были удалены. У поставщика app.json по умолчанию вместо этого есть эквивалентные атрибуты.

Изменено в версии 2.3: ENV был удален.

Журнал изменений

Изменено в версии 2.2: Удалено PRESERVE_CONTEXT_ON_EXCEPTION.

Изменено в версии 1.0: LOGGER_NAME и LOGGER_HANDLER_POLICY были удалены. См. Ведение журнала для получения информации о конфигурации.

Добавлен ENV, чтобы отразить переменную среды FLASK_ENV.

Добавлен SESSION_COOKIE_SAMESITE, чтобы управлять параметром SameSite куки сессии.

Добавлен 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 tomllib
app.config.from_file("config.toml", load=tomllib.load, text=False)

Или из файла 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.

Рекомендации по настройке

Недостатком ранее упомянутого подхода является то, что тестирование становится немного сложнее. Нет единого 100%-го решения для этой проблемы в общем случае, но есть несколько моментов, которые вы можете учитывать, чтобы улучшить этот опыт:

  1. Создавайте своё приложение в функции и регистрируйте голубые печати в нём. Таким образом, вы можете создавать несколько экземпляров приложения с различными привязанными конфигурациями, что значительно упрощает тестирование. Вы можете использовать это для передачи конфигурации по мере необходимости.
  2. Не пишите код, которому нужна конфигурация во время импорта. Если ограничиться доступом к конфигурации только во время запроса, вы можете перенастраивать объект по мере необходимости.
  3. Убедитесь, что конфигурация загружается очень рано, чтобы расширения могли получить доступ к конфигурации при вызове 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.3.x/config/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API