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!")
Π Π΅Π΄Π°ΠΊΡΠΈΡΠΎΠ²Π°ΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΊΠΎΠ½ΡΠΈΠ³ΠΎΠ² ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎ Π°Π΄ΡΠ΅ΡΡ 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/ -
ΠΠ°ΠΏΠΈΡΠΈΡΠ΅ Π½Π°ΠΌ!