openwisp / openwisp/openwisp-utils
[feature] Add a web interface for selected runtime settings
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 93
- Forks
- 104
- Avg merge
- 14h 10m
- Merged PRs (30d)
- 22
Description
⚠️ NOT SUITED TO BEGINNER CONTRIBUTORS.
Is your feature request related to a problem? Please describe.
Changing an important OpenWISP setting currently requires editing deployment configuration and restarting application processes. This creates friction for administrators and makes simple adjustments harder than they need to be.
We must not expose every Django setting or write database values back into django.conf.settings. Django advises applications not to alter settings at runtime, and many OpenWISP modules copy settings into module-level constants during import. For example, openwisp_utils.settings loads API and Celery values this way. Other settings control application startup, model definitions, URL loading, worker connections, or security and cannot change safely while processes are running.
Describe the solution you'd like
Add a web interface for a small, explicit allowlist of settings that are safe to read at runtime.
Use django-constance as the initial implementation candidate, behind an OpenWISP-owned API. It is the strongest fit among the established packages reviewed below because it provides a code-defined allowlist, typed fields, validation, Django admin integration, database persistence, and safe use of a shared cache across processes.
Each OpenWISP module should be able to declare the runtime settings it owns. A declaration should contain a namespaced key, default value, type, label, help text, and validators. The declarations should be collected in a deterministic order. Duplicate keys and invalid declarations should cause a clear Django system check error.
Application code should read these values through the OpenWISP runtime-settings API at the point of use. It must not copy them into django.conf.settings or module-level constants. Existing static settings should remain the default when no database override exists.
The first version should meet these requirements:
- show only settings explicitly marked as runtime-editable by an OpenWISP module;
- allow only superusers to change values initially;
- prevent users from adding, deleting, or renaming settings;
- validate types, choices, ranges, and module-specific rules before saving;
- use the database as the durable source of truth;
- use a shared cache such as Redis when caching is enabled, and reject local-memory caching because it cannot invalidate values across processes;
- make changes visible to all web and Celery processes without a restart, within a documented consistency limit;
- record who changed each value, the old and new values, and when the change happened;
- use the same validation path for admin, management commands, and programmatic writes;
- document which settings remain static and require a restart;
- include multi-process tests proving that one process sees a change made by another;
- include focused tests for permissions, validation, duplicate declarations, audit records, and fallback to static defaults.
Do not make these values runtime-editable:
- credentials, tokens, private keys, signing keys, and other secrets;
DATABASES,CACHES,INSTALLED_APPS,MIDDLEWARE, URL configuration, model or migration settings, storage backends, and authentication backends;- Redis, Celery, email, database, and object-storage connection settings;
- any setting read during imports or process startup, unless every consumer is first changed to read it safely at runtime.
Start with a few low-risk settings. Before adding a setting to the interface, verify every place where it is read and define what happens if it changes while work is in progress.
This work is related to openwisp-utils issue #408, which covers clean module-provided defaults and conflicts between modules. The runtime-settings declarations should reuse that mechanism if the final design makes this practical, but static defaults and runtime-editable values must remain separate concepts.
Describe alternatives you've considered
Research snapshot from August 28, 2026. GitHub stars are included only as a rough adoption signal and will change over time.
| Package | Adoption and maintenance | Strengths | Main concerns for OpenWISP |
|---|---|---|---|
django-constance |
1,851 stars; version 4.3.5 released March 15, 2026 | Code-defined allowlist, typed admin form, database and Redis backends, shared-cache safety check, async access | One global registry and coarse permission; no built-in audit history or secret storage; direct Python writes need an OpenWISP validation wrapper |
django-solo |
966 stars; version 2.5.1 released January 1, 2026 | Simple singleton models, standard model fields and validation, focused admin | Requires migrations as fields change, has no cross-module declaration registry, and uses an unusual CC BY 3.0 license that needs review |
django-extra-settings |
618 stars; version 0.15.0 released July 13, 2026 | Actively maintained, many types, admin and cache support | Admin users can create, rename, and delete arbitrary settings by default; documented local-memory cache setup is unsafe across processes |
django-dynamic-preferences |
360 stars; version 1.17.0 released January 10, 2025 | Per-module declaration files, global and per-object preferences, validators, admin and forms | Extra per-user and per-object complexity is not needed initially; cache safety depends on deployment configuration; compatibility documentation is inconsistent with package metadata |
django-waffle was also reviewed. It is a good choice for feature flags and gradual rollouts, but it is not a general typed settings system.
django-constance should use its database backend and a shared Redis cache. Its local caching Redis backend should not be used because each process may keep an old value until its local timeout expires. Constance has no built-in secret protection or complete audit log, so OpenWISP must add those boundaries itself.
Additional context
- Django runtime settings guidance: https://docs.djangoproject.com/en/5.2/topics/settings/#altering-settings-at-runtime
- django-constance configuration and admin: https://django-constance.readthedocs.io/en/latest/
- django-constance database and cache behavior: https://django-constance.readthedocs.io/en/latest/backends.html#database
- django-dynamic-preferences declarations and cache behavior: https://django-dynamic-preferences.readthedocs.io/en/latest/quickstart.html
- django-solo model and cache approach: https://github.com/lazybird/django-solo/blob/2.5.1/README.md
- django-extra-settings behavior: https://github.com/fabiocaccamo/django-extra-settings/blob/0.15.0/README.md
This issue should not include organization-specific or user-specific preferences in its first version. Those have different permission and data-lifecycle requirements and can be considered separately.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with openwisp_utils.settings and related openwisp-utils issue #408, then read the django-constance database and cache documentation. No implementation files or tests are named; the work is done when the explicit declaration, validation, permissions, audit, fallback, cache, and multi-process behavior are defined and covered by focused tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python, redis
- Domain
- api, backend, database
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100