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. Для удобного администрирования конфиги поддерживают
- теги и топики для группировки и поиска
- документацию
- автоматическую загрузку новых конфигов в бд
- валидацию при изменении (типы и значения)
- сохранение даты последних изменений и чтений конфигов
- импорт и экспорт (удобно для тестирования системы)
Как начать пользоваться
- Установите пакет
django-liveconfigs
через pip, poetry или еще как-нибудь.
pip install django-liveconfigs
- Добавьте "liveconfigs" в INSTALLED_APPS в settings:
INSTALLED_APPS = [
...,
"import_export",
"liveconfigs",
]
- Добавьте в 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
- Заведите себе файл собственно с конфигами, например
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
- Используете где-нибудь
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. Для этого:
- Установите переменную LIVECONFIGS_SYNCWRITE в
settings.py
в False:
LIVECONFIGS_SYNCWRITE = False # async write mode
- Если используете 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'
},
}
- Если используете не Celery, то адаптируйте этот код под ваш случай
Остались вопросы?
-
Посмотрите примеры использования конфигов: https://github.com/liveconfigs/django-liveconfigs-example/
-
Примеры использования валидаторов : https://github.com/liveconfigs/django-liveconfigs-example/
-
Примеры валидаторов :
validators.py
в https://github.com/liveconfigs/django-liveconfigs/ -
Напишите нам!
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
Built Distribution
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
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5e61050462ff4062e81d8f9501ed5bf20c33bfca1eba868d9afff3c2aac76931 |
|
MD5 | a3e8653b07d85b8d24af2c801acb5602 |
|
BLAKE2b-256 | 7391694e861fd144881fe7c41cbd75025ee4391446ecddbd6e00d9cd6d63d5bb |
File details
Details for the file django_liveconfigs-1.0.6.1-py3-none-any.whl
.
File metadata
- Download URL: django_liveconfigs-1.0.6.1-py3-none-any.whl
- Upload date:
- Size: 23.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 05fc2dcd7dc59c791ef7f1d2a8d8b27d0819bac565c51c885904b6cc76023c1a |
|
MD5 | 35c67cd35bbc16bfe8b75655d19f4f61 |
|
BLAKE2b-256 | b8d8b307c3ef98295f3696907060d5a2e2d5220e0dfe476f4c425dae71f36ea8 |