A type-safe, dataclass-based approach to Django settings configuration that provides better IDE support, validation, and maintainability.
pip install django-settings
# settings.py
from pathlib import Path
from django_settings import DjangoSettings, DjangoDatabases, DatabaseConfig
BASE_DIR = Path(__file__).resolve().parent.parent
class DatabaseSettings(DjangoDatabases):
default = DatabaseConfig(
engine='django.db.backends.sqlite3',
name= 'db.sqlite3'
)
# Create settings instance
settings = DjangoSettings(
template_dirs = [BASE_DIR / 'templates'], # Pass template_dirs if you want to load templates from other places outside app directories.
debug=True,
secret_key="your-secret-key-here",
allowed_hosts=["localhost", "127.0.0.1"],
databases=DatabaseSettings()
)
# Register settings globally
settings.register()
# settings/base.py
from django_settings import DjangoSettings
class BaseSettings(DjangoSettings):
def __init__(self):
super().__init__(
debug=False,
secret_key="base-secret-key",
installed_apps=[
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp',
],
middleware=[
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
)
# settings/development.py
from .base import BaseSettings
settings = BaseSettings()
settings.debug = True
settings.allowed_hosts = ["localhost", "127.0.0.1"]
settings.register()
# settings/production.py
from .base import BaseSettings
from django_settings import DatabaseConfig, DjangoDatabases
import os
class ProductionDatabases(DjangoDatabases):
default = DatabaseConfig(
engine='django.db.backends.postgresql',
name=os.environ['DB_NAME'],
user=os.environ['DB_USER'],
password=os.environ['DB_PASSWORD'],
host=os.environ['DB_HOST'],
port=os.environ['DB_PORT']
)
settings = BaseSettings()
settings.debug = False
settings.secret_key = os.environ['SECRET_KEY']
settings.allowed_hosts = os.environ['ALLOWED_HOSTS'].split(',')
settings.databases = ProductionDatabases()
settings.register()
- Type Safety: Full type hints for all Django settings
- IDE Support: Autocomplete and validation in your IDE
- Default Values: Sensible defaults for all Django settings
- Validation: Dataclass validation ensures correct types
- Backwards Compatible: Works with existing Django projects
- Custom settings: Support custom/extra Django settings
from django_settings import DjangoSettings, DatabaseConfig, DjangoDatabases
# Define individual database configurations
class MyDatabases(DjangoDatabases):
default = DatabaseConfig(
engine='django.db.backends.postgresql',
name='myproject',
user='myuser',
password='mypassword',
host='localhost',
port='5432'
)
users = DatabaseConfig(
engine='django.db.backends.mysql',
name='users_db',
user='mysql_user',
password='mysql_password',
host='mysql.example.com',
port='3306'
)
settings = DjangoSettings(
databases=MyDatabases()
)
# With additional options
class ProductionDatabases(DjangoDatabases):
default = DatabaseConfig(
engine='django.db.backends.postgresql',
name='production_db',
user='prod_user',
password='secure_password',
host='db.example.com',
port='5432',
options={
'sslmode': 'require',
'connect_timeout': 10,
},
conn_max_age=600,
conn_health_checks=True,
atomic_requests=True
)
settings = DjangoSettings(
email_backend='django.core.mail.backends.smtp.EmailBackend',
email_host='smtp.gmail.com',
email_port=587,
email_use_tls=True,
email_host_user='[email protected]',
email_host_password='your-app-password',
default_from_email='[email protected]'
)
settings = DjangoSettings(
caches={
'default': {
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
},
'sessions': {
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/2',
}
}
)
settings = DjangoSettings(
debug=False,
allowed_hosts=['yourdomain.com', 'www.yourdomain.com'],
secure_ssl_redirect=True,
secure_hsts_seconds=31536000,
secure_hsts_include_subdomains=True,
secure_hsts_preload=True,
secure_content_type_nosniff=True,
session_cookie_secure=True,
csrf_cookie_secure=True,
x_frame_options='DENY'
)
from django_settings import DjangoSettings, ExtraSettings
class CustomSettings(ExtraSettings):
ipinfo_token = 'XXXXXXXXXX'
# Create settings instance
settings = DjangoSettings(
debug=True,
secret_key="your-secret-key-here",
allowed_hosts=["localhost", "127.0.0.1"],
...,
extra=CustomSettings()
)
# Register settings globally
settings.register()
The main class that contains all Django settings as typed attributes.
register()
: Registers settings as module-level variablesto_dict
: Property that returns settings as a dictionary with uppercase keys
A dataclass for defining individual database configurations with type safety.
engine
: Database backend enginename
: Database nameuser
: Database userpassword
: Database passwordhost
: Database hostport
: Database portoptions
: Additional database optionsatomic_requests
: Enable atomic requestsconn_max_age
: Connection max ageconn_health_checks
: Enable connection health checks
A collection class for managing multiple database configurations.
class MyDatabases(DjangoDatabases):
default = DatabaseConfig(engine='django.db.backends.sqlite3')
cache = DatabaseConfig(engine='django.db.backends.postgresql')
# Lowercase attribute access
print(settings.debug) # True
# Uppercase Django-style access
print(settings.DEBUG) # True
# Dictionary access
settings_dict = settings.as_dict
print(settings_dict['DEBUG']) # True
DEBUG = True
SECRET_KEY = 'your-secret-key'
ALLOWED_HOSTS = ['localhost']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'db.sqlite3',
}
}
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
# ...
]
from django_settings import DjangoSettings, DatabaseConfig, DjangoDatabases
class MyDatabases(DjangoDatabases):
default = DatabaseConfig(
engine='django.db.backends.sqlite3',
name='db.sqlite3'
)
settings = DjangoSettings(
debug=True,
secret_key='your-secret-key',
allowed_hosts=['localhost'],
databases=MyDatabases()
)
settings.register()
- Python 3.10+
- Django 3.2+
MIT License