Skip to main content

Simple powerful and convenient configs for Django

Project description

LiveConfigs

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

Быстрый пример

Создаем настройки

class MyConfig(liveconfigs.BaseConfig):
   IS_FEATURE_ENABLED: bool = False
   NEW_FEATURE_VALUE: float = 20.4

Используем их

if MyConfig.IS_FEATURE_ENABLED:
   print('feature is enabled and feature value is', MyConfig.NEW_FEATURE_VALUE)

Меняем через админку!

Экран редактирования конфига

Термины

  • настройка, конфиг - одно типизированное именованное значение
  • класс конфига, группа настроек - настройки, объединенные в один класс python
  • топик - общая "тема" для группы настроек, по которой можно производить поиск настроек в админке. У разных групп настроек в принципе может быть один и тот же топик
  • теги - ключевые слова для быстрого поиска настроек. Одна настройка может иметь несколько тегов

Со стороны разработчика

Для разработчика настройки выглядят как статические члены-константы классов python. Их можно быстро добавить, убрать, их просто использовать (пара строк кода). Их понимает mytype и среды разработки.

За создание новых конфигов отвечает разработчик. Значения по-умолчанию хранятся в коде. В БД новые конфиги попадают при выкатке или при первом использовании.

Со стороны администратора

Значения задаются через админку django. Для удобного администрирования конфиги поддерживают

  • теги и топики для группировки и поиска
  • документацию
  • автоматическую загрузку новых конфигов в бд
  • валидацию при изменении (типы и значения)
  • сохранение даты последних изменений и чтений конфигов
  • импорт и экспорт (удобно для тестирования системы)

Экран поиска и фильтрации конфигов

Как начать пользоваться

  1. Установите пакет django-liveconfigs через pip, poetry или еще как-нибудь.
pip install django-liveconfigs
  1. Добавьте "liveconfigs" в INSTALLED_APPS в settings:
    INSTALLED_APPS = [
        ...,
        "import_export",
        "liveconfigs",
    ]
  1. Добавьте в settings еще несколько строк.
    # liveconfigs settings
    # Максимальная длина текста в значении конфига при которой отображать поле редактирования конфига как textinput
    # При длине текста в значении конфига большей этого значения - отображать поле редактирования конфига как textarea
    LC_MAX_STR_LENGTH_DISPLAYED_AS_TEXTINPUT = 50
    LC_ENABLE_PRETTY_INPUT = True
    LIVECONFIGS_SYNCWRITE = True    # sync write mode
    LC_CACHE_TTL = 1    # cache TTL in seconds (default = 1)
    # Максимальная длина значения конфига (в текстовом представлении) при которой значение в списке выводится целиком
    # При бОльшей длине визуал значения будет усечен ("Длинная строка" -> "Длин ... рока")
    LC_MAX_VISUAL_VALUE_LENGTH = 50
  1. Заведите себе файл собственно с конфигами, например config/config.py
from liveconfigs import models
from liveconfigs.validators import greater_than
from enum import Enum

# isort: off

# config_row_update_signal_handler begin
from django.conf import settings
from django.dispatch import receiver
from liveconfigs.signals import config_row_update_signal
from liveconfigs.tasks import config_row_update_or_create

# FIXME: Импорт приложения Celery из вашего проекта (если используете Celery)
# FIXME: Вам нужно изменить этот код, если вы используете не Celery
from celery_app import app

# isort: on

# Пример для Celery
# Реальное сохранение данных выполняет функция config_row_update_or_create
# Реализуйте отложенное сохранение удобным для вас методом
# Для Celery зарегистрируйте эту задачу в CELERY_TASK_ROUTES
# FIXME: Вам нужно изменить этот код, если вы используете не Celery
@app.task(max_retries=1, soft_time_limit=1200, time_limit=1500)
def config_row_update_or_create_proxy(config_name: str, update_fields: dict):
    config_row_update_or_create(config_name, update_fields)


@receiver(config_row_update_signal, dispatch_uid="config_row_update_signal")
def config_row_update_signal_handler(sender, config_name, update_fields, **kwargs):
    # Пример для Celery
    # При настройках для синхронного сохранения функция будет вызвана напрямую
    if settings.LIVECONFIGS_SYNCWRITE:
        config_row_update_or_create_proxy_func = config_row_update_or_create_proxy
    # При настройках для асинхронного сохранения функция будет вызвана через delay
    # FIXME: Вам нужно изменить этот код, если вы используете не Celery
    else:
        config_row_update_or_create_proxy_func = config_row_update_or_create_proxy.delay

    config_row_update_or_create_proxy_func(config_name, update_fields)


# config_row_update_signal_handler end


# тут перечислены возможные теги для настроек из вашей предметной области
class ConfigTags(str, Enum):
    front = "Настройки для фронта"
    features = "Фичи"
    basic = "Основные"
    other = "Прочее"

# тут описана сама настройка и ее мета-данные
class FirstExample(models.BaseConfig):
    __topic__ = 'Основные настройки'  # короткое описание группы настроек
    MY_FIRST_CONFIG: int = 40
    # следующие строчки необязательны
    MY_FIRST_CONFIG_DESCRIPTION = "Какая-то моя настройка"
    MY_FIRST_CONFIG_TAGS = [ConfigTags.basic, ConfigTags.other]
    MY_FIRST_CONFIG_VALIDATORS = [greater_than(5)]
    
    # вторая настройка, без метаданных
    SECOND_ONE: bool = False  
  1. Используете где-нибудь FirstExample.MY_FIRST_CONFIG как обычный int:
from config.config import FirstExample
...
if FirstExample.MY_FIRST_CONFIG > 20:
    print("Hello there!")

Просмотр и редактирование конфигов в админке django

Редактировать значения конфигов можно по адресу http://YOUR_HOST/admin/liveconfigs/configrow/

При установке значений проверяется тип нового значения, а также вызываются дополнительные валидаторы

Автоматическая загрузка новых конфигов в БД

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

Если по какой-то причине вы не хотите ждать, то залить все новые конфиги в БД можно и на старте сервиса, добавив в ваш скрипт запуска вызов команды load_config:

    # какие-то старые команды
    python /app/manage.py migrate --noinput
    python /app/manage.py collectstatic --noinput

    #  НОВАЯ СТРОЧКА - загрузка конфигов в бд
    python /app/manage.py load_config

    #  сам запуск сервиса - может быть и так
    python /app/manage.py runserver_plus 0.0.0.0:8080 --insecure

Даты последнего изменения и чтения

В БД у каждой настройки есть два дополнительных поля - даты последнего чтения и записи. Они помогают определить в живой системе, нужны ли все еще какие-то настройки или пора уже от них избавиться.

Асинхронная запись

Чтобы запись последней даты чтения не тормозила вам всю систему (если,например, конфиги часто читаются разными частями кода), можно вынести ее в задачу celery. Для этого:

  1. Установите переменную LIVECONFIGS_SYNCWRITE в settings.py в False:
    LIVECONFIGS_SYNCWRITE = False   # async write mode
  1. Если используете Celery, то настройте запуск задачи config.config.config_row_update_or_create_proxy:
    CELERY_TASK_ROUTES = {
        'config.config.config_row_update_or_create_proxy': {
            'queue': 'quick', 'routing_key': 'quick'
        },
    }
  1. Если используете не Celery, то адаптируйте этот код под ваш случай

Остались вопросы?

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_liveconfigs-1.0.6.1.tar.gz (17.9 kB view details)

Uploaded Source

Built Distribution

django_liveconfigs-1.0.6.1-py3-none-any.whl (23.3 kB view details)

Uploaded Python 3

File details

Details for the file django_liveconfigs-1.0.6.1.tar.gz.

File metadata

  • Download URL: django_liveconfigs-1.0.6.1.tar.gz
  • Upload date:
  • Size: 17.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.5

File hashes

Hashes for django_liveconfigs-1.0.6.1.tar.gz
Algorithm Hash digest
SHA256 5e61050462ff4062e81d8f9501ed5bf20c33bfca1eba868d9afff3c2aac76931
MD5 a3e8653b07d85b8d24af2c801acb5602
BLAKE2b-256 7391694e861fd144881fe7c41cbd75025ee4391446ecddbd6e00d9cd6d63d5bb

See more details on using hashes here.

File details

Details for the file django_liveconfigs-1.0.6.1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_liveconfigs-1.0.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 05fc2dcd7dc59c791ef7f1d2a8d8b27d0819bac565c51c885904b6cc76023c1a
MD5 35c67cd35bbc16bfe8b75655d19f4f61
BLAKE2b-256 b8d8b307c3ef98295f3696907060d5a2e2d5220e0dfe476f4c425dae71f36ea8

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page