WebCase Settings
A flexible Django settings framework for defining, validating, and managing application-wide and per-user settings using Pydantic DTOs, Django ORM, and lazy resolvers.
Installation
pip install wc-django-settings
In settings.py:
INSTALLED_APPS += [
'wcd_settings',
]
MIDDLEWARE += [
'wcd_settings.middleware.settings_middleware',
]
Usage
1. Defining and Registering Settings
1.1 Define DTOs (Pydantic Models)
Create Pydantic models to define the shape and validation of your settings.
# myapp/dtos.py
from wcd_settings.registries import SettingsDTO
class ThemeSettings(SettingsDTO):
color_scheme: str = Field(default='light', description='Theme color scheme')
font_size: int = Field(default=14, ge=8, le=32, description='Font size in px')
class NotificationsSettings(SettingsDTO):
enabled: bool = Field(default=True, description='Enable notifications')
frequency: str = Field(default='daily', description='Notification frequency')
1.2 Register DTOs
Register these models with app_settings_registry (for global settings) or user_settings_registry (for per-user settings).
# myapp/registry.py
from wcd_settings.registries import (
AppSettingsDescriptor, UserSettingsDescriptor,
app_settings_registry, user_settings_registry,
)
from .dtos import ThemeSettings, NotificationsSettings
# Application-wide setting
app_settings_registry.register(
AppSettingsDescriptor(
# Unique key
key='theme',
# DTO model to validate settings
dto=ThemeSettings,
# Optional json schema object that describes DTO
schema=ThemeSettings.model_json_schema(),
# Defines whether this object could be edited through HTTP API
is_editable=False,
# Defines whether this object could be accessed through HTTP API
is_readable=True,
)
)
# User-specific setting
user_settings_registry.register(
UserSettingsDescriptor(
key='notifications', dto=NotificationsSettings,
schema=NotificationsSettings.model_json_schema(),
is_editable=True, is_readable=True,
)
)
2. Fetching Settings with Resolvers
Resolvers provide lazy-loading and caching of settings from the database.
from wcd_settings import shortcuts
# App Settings
# Optional request parameter to use middleware-injected settings and cahe
app_settings = shortcuts.app_settings(request=None)
theme: Optional[ThemeSettings] = app_settings.resolver.get('theme')
print(theme.color_scheme) # "light" by default or DB value
# User Settings
user_settings = shortcuts.user_settings(request=None)
# Getting settings for user_id=42
notifications: Optional[NotificationsSettings] = user_settings.resolver.get((42, 'notifications'))
if notifications.enabled:
print('User has notifications enabled')
Or without shortcuts:
from wcd_settings.resolvers import (
make_app_resolver, make_user_resolver,
)
from wcd_settings.setters import (
make_app_setter, make_user_setter,
)
app_resolver = make_app_resolver()
user_resolver = make_user_resolver()
# You may use resolvers separately:
theme: Optional[ThemeSettings] = app_resolver.get('theme')
notifications: Optional[NotificationsSettings] = user_resolver.get((42, 'notifications'))
# And them create setters based on them:
app_settings = make_app_setter(app_resolver)
user_settings = make_user_setter(user_resolver)
3. Updating Settings with Setters
Setters update settings in the database with full Pydantic validation.
3.1 Application Settings Setter
from wcd_settings import shortcuts
from myapp.dtos import ThemeSettings
app_settings = shortcuts.app_settings(request=None)
# Update theme settings
theme_dto = ThemeSettings(color_scheme='dark', font_size=16)
app_settings.save('theme', theme_dto)
3.2 User Settings Setter
from wcd_settings.setters import make_user_setter
from myapp.dtos import NotificationsSettings
user_settings = shortcuts.user_settings(request=None)
# Update user notifications settings
user_id = 42
notif_dto = NotificationsSettings(enabled=False, frequency='weekly')
user_settings.save((user_id, 'notifications'), notif_dto)
4 Access Settings in Views
Use the request.app_settings and request.user_settings properties injected by middleware.
# views.py
from django.http import JsonResponse
def profile_view(request):
theme = request.app_settings.resolver.get('theme')
notifications = request.user_settings.resolver.get((request.user.id, 'notifications'))
return JsonResponse({
'theme': theme.color_scheme,
'notifications_enabled': notifications.enabled,
})
5. Advanced Usage
5.1 Partial Updates
You can update nested fields within a settings DTO:
from wcd_settings.setters import AppSettingsSetAction
actions = [
AppSettingsSetAction(key='theme', path=['font_size'], value=18),
AppSettingsSetAction(key='theme', path=['color_scheme'], value='dark'),
]
setter = make_app_setter(make_app_resolver())
commit, failures = setter.set(actions)
if not failures:
commit() # Save changes
You may even inject values into more complex datastructures
from wcd_settings.setters import UserSettingsSetAction
from wcd_settings.registries import (
SettingsDTO, UserSettingsDescriptor,
user_settings_registry,
)
from wcd_settings.resolvers import make_user_resolver
from wcd_settings.setters import make_user_setter
class Nested(SettingsDTO):
value: List[Optional[str]] = Field(default_factory=list)
class Complex(SettingsDTO):
title: Optional[str] = None
nested: Nested = Field(default_factory=Nested)
# User-specific setting
user_settings_registry.register(
UserSettingsDescriptor(
key='complex', dto=Complex,
schema=Complex.model_json_schema(),
is_editable=True, is_readable=True,
)
)
actions = [
UserSettingsSetAction((1, 'complex'), path=['title'], value='Title'),
UserSettingsSetAction(
(1, 'complex'),
# Path could also inject values by list indexes:
path=['nested', 'value', 0],
value='first',
),
UserSettingsSetAction(
(1, 'complex'),
# Even if index is larger than current data length all the previous
# items in the list will be filled with `None`'s.
# Be aware, that DTO validation should also support that.
path=['nested', 'value', 3],
value='fourth',
),
]
setter = make_user_setter(make_user_resolver())
commit, failures = setter.set(actions)
if not failures:
commit() # Save changes
6. Views
# urls.py
from wcd_settings.urls import make_urlpatterns
# This will add views for getting and editing app and user settings:
urlpatterns += make_urlpatterns()
After that you may call:
/api/v1/settings/app/all/- Retrieving all the app settings./api/v1/settings/app/set/- Setting the values for the app settings./api/v1/settings/own/all/- Retrieving all the current user's settings./api/v1/settings/own/set/- Setting the values for the current user's settings.
From the example above calling the /api/v1/settings/own/set/ with:
{
"actions": [
{"path": ["complex", "title"], "value": "Title"},
{"path": ["complex", "nested", "value", 0], "value": "one"},
]
}
Will update the user's settings to the following:
settings = Complex(
title='Title',
nested=Nested(
value=['one'],
),
)
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[0.1.2]
Getters and setters are fully functional.
[0.1.0]
Initial version.
Metadata
Release files for wc-django-settings 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wc_django_settings-0.1.2.tar.gz | 36.2 kB | Details |
Release files / wc_django_settings-0.1.2.tar.gz
| Download URL | wc_django_settings-0.1.2.tar.gz |
|---|---|
| Size | 36.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dd5c9d87616ccd1dba8b7cc87225c99a834247d5d05a5343bc5cbcc56da44bf8
|
|
BLAKE2b-256 checksum How to use checksums |
d3c4f47e30b1f884c57bc9190af2ae8c9d88ba7cbaf0db8d61043575b34fc95f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.8
|