L'application mayan/apps/smart_settings/ est le système de configuration centralisé de Mayan EDMS. Elle gère la résolution des valeurs de configuration depuis plusieurs sources (variables d'environnement, fichier config.yml, base de données), leur validation, leur cache, et leur interface d'édition via l'UI.
SettingCluster (primary)
├── Domain 1 : Django settings (priorité 10)
├── Domain 2 : Fichier config.yml (priorité 20)
├── Domain 3 : Variables d'environnement (priorité 30) ← priorité la plus haute
└── Domain 4 : Modèle DB (priorité 40)
│
├── SettingNamespace (ex. 'documents')
│ ├── Setting MAYAN_DOCUMENTS_LANGUAGE_CODES
│ └── Setting MAYAN_DOCUMENTS_STUB_EXPIRATION_INTERVAL
└── SettingNamespace (ex. 'storage')
└── Setting MAYAN_STORAGE_BACKEND
Priorité : la valeur lue par le domaine de priorité la plus haute (nombre le plus grand) gagne. Ainsi, une variable d'environnement (priorité 30) écrase toujours le fichier config (priorité 20).
SettingDomainDjango (priorité 10)Lit les valeurs depuis django.conf.settings — les valeurs par défaut codées dans le code Python.
SettingDomainConfigurationFile (priorité 20)Lit depuis le fichier config.yml (chemin dans CONFIGURATION_FILEPATH, typiquement media/config.yml).
@functools.cache pour accélérer le démarrage.CONFIGURATION_LAST_GOOD_FILEPATH (media/config_backup.yml).mayan-manage settings_revert copie config_backup.yml → config.yml pour revenir à la dernière configuration valide.SettingDomainEnvironmentVariable (priorité 30)Lit depuis les variables d'environnement avec le préfixe MAYAN_ :
MAYAN_DOCUMENTS_LANGUAGE_CODES='["fr", "en"]' → parsed comme YAML
Les valeurs sont désérialisées en YAML (donc true/false, listes, dicts sont tous supportés).
SettingDomainModel (priorité 40)Stocke les valeurs en attente dans la table smart_settings_updatedstoredssetting (modèle UpdatedStoredSetting). Utilisé par l'interface d'édition UI pour stocker les modifications avant le prochain redémarrage. Ces valeurs sont effacées au démarrage (do_ready()) une fois absorbées dans le fichier config.
SettingClusterLe cluster orchestre tous les namespaces et domaines. Il y a un seul cluster dans Mayan : setting_cluster (alias de setting_cluster_primary).
from mayan.apps.smart_settings.settings import setting_cluster
# Créer un namespace pour votre app
setting_namespace = setting_cluster.do_namespace_add(
label=_('My App'), name='myapp'
)
Le cluster charge automatiquement les modules settings.py de toutes les apps via AppsModuleLoaderMixin (_loader_module_name = 'settings').
SettingNamespaceRegroupe les settings d'une app sous un préfixe commun. Singleton (deux appels avec le même name lèvent ImproperlyConfigured).
# Dans myapp/settings.py
from mayan.apps.smart_settings.settings import setting_cluster
setting_namespace = setting_cluster.do_namespace_add(
label=_('My App'),
name='myapp',
version='0002', # optionnel : pour les migrations de settings
migration_class=MyMigrations # optionnel
)
setting_my_value = setting_namespace.do_setting_add(
default=42,
global_name='MYAPP_MY_VALUE',
help_text=_('Description du setting'),
data_type=int, # coercion automatique
choices=(10, 42, 100), # valeurs autorisées
validation_function=my_validator, # validation custom
post_edit_function=my_post_edit, # callback après modification
)
SettingChaque setting est identifié par son global_name unique (convention : APPNAME_SETTING_NAME en majuscules, sans préfixe MAYAN_ — le préfixe est ajouté automatiquement pour la lecture des variables d'environnement).
setting.value
→ si pas encore chargée → do_value_load()
1. cluster.get_domains_value(key) → parcourt domaines par priorité croissante
2. do_value_validate() → coercion data_type + validation_function
3. express_promises() → force les lazy translations en str
→ met en cache dans self._value
| Attribut | Description |
|---|---|
global_name |
Identifiant unique ex. DOCUMENTS_LANGUAGE_CODES |
default |
Valeur par défaut Python |
data_type |
Callable de coercion (ex. int, list, bool) |
choices |
Valeurs autorisées (validation) |
validation_function(raw_value, setting) |
Validation custom, doit retourner la valeur |
post_edit_function(setting) |
Appelée après modification (ex. : reconfigurer un backend) |
value_error |
Dernier message d'erreur de validation (ou None) |
# Lecture
setting_my_value.value # → int 42
# Modification en mémoire (tests)
setting_my_value.do_value_override(value=100)
# Marquer comme "en attente" (via l'UI)
setting_my_value.do_value_pending_set(value=100)
# Revenir à la valeur courante (annuler)
setting_my_value.do_value_revert()
SettingNamespaceSingletonAvant que Django ne soit initialisé, Mayan a besoin de certains settings critiques (chemin du fichier de config, base de données, etc.). SettingNamespaceSingleton est une classe de bootstrap indépendante de Django qui résout ces valeurs très tôt :
mayan/settings/base.py
→ SettingNamespaceSingleton(globals())
→ lit MEDIA_ROOT (env > global_symbol_table > défaut)
→ construit CONFIGURATION_FILEPATH = MEDIA_ROOT/config.yml
→ lit config.yml
→ lit env MAYAN_DATABASES
→ injecte dans globals() de base.py
→ Django démarre avec les bonnes valeurs
BaseSetting — ordre de résolution (bootstrap)MAYAN_ + nom)config.ymlbase.pySettings critiques pré-déclarés dans utils.py :
| Setting | Défaut | Description |
|---|---|---|
MEDIA_ROOT |
BASE_DIR/media |
Dossier media |
CONFIGURATION_FILEPATH |
MEDIA_ROOT/config.yml |
Fichier de config principal |
CONFIGURATION_LAST_GOOD_FILEPATH |
MEDIA_ROOT/config_backup.yml |
Dernière config valide |
DATABASES |
None |
Config DB Django |
DEBUG |
False |
Mode debug |
CELERY_BROKER_URL |
memory:// |
Broker Celery |
COMMON_EXTRA_APPS |
() |
Apps supplémentaires |
COMMON_DISABLED_APPS |
() |
Apps désactivées |
SettingNamespaceMigration)Permet de migrer automatiquement les valeurs stockées en config lors d'un changement de format entre versions :
class DocumentsSettingMigration(SettingNamespaceMigration):
# Méthode nommée : {global_name_en_minuscule}_{numéro_version_4_chiffres}
def documents_language_codes_0002(self, value):
# Conversion de l'ancien format (string) vers le nouveau (liste)
if isinstance(value, str):
return [value]
return value
version='0002' et migration_class=DocumentsSettingMigration._namespaces_/documents/version) ≠ la version courante, les méthodes de migration correspondantes sont exécutées dans l'ordre.Les settings sont éditables via l'interface d'administration Mayan :
config.yml via do_make_persistent()| Indicateur | Signification |
|---|---|
get_is_overridden() |
La valeur diffère de la valeur par défaut |
get_has_value_new() |
Une valeur en attente diffère de la valeur active |
get_has_load_error() |
Erreur lors du chargement (fallback sur la valeur par défaut) |
# myapp/settings.py
from django.utils.translation import gettext_lazy as _
from mayan.apps.smart_settings.settings import setting_cluster
setting_namespace = setting_cluster.do_namespace_add(
label=_('My App'), name='myapp'
)
setting_api_key = setting_namespace.do_setting_add(
default='',
global_name='MYAPP_API_KEY',
help_text=_('API key for the external service.'),
)
setting_timeout = setting_namespace.do_setting_add(
default=30,
global_name='MYAPP_TIMEOUT',
data_type=int,
help_text=_('Timeout in seconds.'),
)
# myapp/views.py
from .settings import setting_api_key, setting_timeout
key = setting_api_key.value # '' ou valeur de MAYAN_MYAPP_API_KEY
timeout = setting_timeout.value # 30 ou valeur parsée de config.yml
Configuration dans config.yml :
MYAPP_API_KEY: 'secret-key-here'
MYAPP_TIMEOUT: 60
Ou via variable d'environnement (priorité plus haute) :
MAYAN_MYAPP_API_KEY='secret-key-here'
MAYAN_MYAPP_TIMEOUT='60'