Сообщить об ошибке.

Способы хранения, загрузки и переключения конфигураций Flask.

Содержание:


Хранение и загрузка конфигурации Flask из файлов Python.

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

Общий шаблон таков:

app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')

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

# bash Linux
$ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg
$ flask run
 * Running on http://127.0.0.1:5000/

# CMD Windows
> set YOURAPPLICATION_SETTINGS=\path\to\settings.cfg
> flask run
 * Running on http://127.0.0.1:5000/

# Powershell Windows
> $env:YOURAPPLICATION_SETTINGS = "\path\to\settings.cfg"
> flask run
 * Running on http://127.0.0.1:5000/

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

Вот пример файла конфигурации:

# Пример конфигурации
SECRET_KEY = b'_5#y2L"F4Q8z\n\xec]/'

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

Хранение и загрузка конфигурации Flask из .json, .toml и т. д.

Также можно загрузить конфигурацию из файла в любом формате по вашему выбору с помощью метода объекта конфигурации app.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 из переменных среды окружения.

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

Переменные среды можно установить в оболочке терминала перед запуском сервера:

# bash Linux
$ export SECRET_KEY="5f352379324c22463451387a0aec5d2f"
$ export MAIL_ENABLED=false
$ flask run
 * Running on http://127.0.0.1:5000/

# CMD Windows
> set SECRET_KEY="5f352379324c22463451387a0aec5d2f"
> set MAIL_ENABLED=false
> flask run
 * Running on http://127.0.0.1:5000/

Важно помнить, что переменные среды являются строками - они не десериализуются автоматически в типы 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")

Обратите внимание, что любое значение, кроме пустой строки, будет интерпретироваться как логическое значение True в Python, что требует осторожности, если среда явно устанавливает значения, предназначенные для False.

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

Есть и другие методы для объекта конфигурации для загрузки из отдельных файлов. Для получения полной справки прочтите документацию по объекту flask.Config.

Некоторые рекомендации по настройке приложений на Flask.

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

  1. Создавайте экземпляр веб-приложения в функции и регистрируйте в нем схемы blueprint. Таким образом, можно создать несколько экземпляров приложения с разными подключенными конфигурациями, что значительно упростит модульное тестирование. Такой подход можно использовать для передачи конфигурации по мере необходимости.
  2. Не пишите код, который требует настройки во время импорта.

Переключение конфигураций.

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

app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')

Затем нужно добавить отдельный файл config.py и экспортировать YOURAPPLICATION_SETTINGS=/path/config.py, и все готово. Но есть и альтернативные способы. Например, можно использовать импорт или создание подклассов.

В мире Django, очень популярно в файле конфигурации делать явный импорт, добавив from yourapplication.default_settings import * в начало файла, а затем переопределять изменения вручную. Во Flask, например, можно проверять переменную среды окружения, такую ​​как 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

Чтобы включить такую ​​конфигурацию, нужно вызвать app.config.from_object():

app.config.from_object('configmodule.ProductionConfig')

Обратите внимание, что app.config.from_object() не создает экземпляр объекта класса. Если нужно создать экземпляр класса, например, для доступа к свойству, то необходимо сделать это перед вызовом app.config.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):
    """Базовая конфигурация, использует 
    промежуточный сервер баз данных."""
    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):
    """Использует сервер базы данных для production."""
    DB_SERVER = '192.168.19.32'

class DevelopmentConfig(Config):
    DB_SERVER = 'localhost'

class TestingConfig(Config):
    DB_SERVER = 'localhost'
    DATABASE_URI = 'sqlite:///:memory:'

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

Так же смотрите как можно загружать конфигурации из папки экземпляра приложения.