Declaratively setup Django before deployment in any environment
Project description
Django Setup Tools
Django Setup Tools is a Django package that enables declarative configuration of setup scripts for Django applications. It provides a simple way to run initialization scripts and ongoing maintenance tasks in different environments during deployment.
What It Does
Django Setup Tools allows you to:
- Run initialization scripts only when the database is first set up
- Execute maintenance tasks every time the setup command runs
- Configure different behaviors for different environments (development, staging, production)
- Mix Django management commands with custom Python functions
- Ensure consistent deployment across different environments
Key Features
- 🚀 Environment-specific configurations - Different scripts for dev, staging, production
- 🔄 One-time and recurring scripts - Scripts that run only on initial setup vs. every deployment
- 🛠 Flexible command types - Support for Django management commands and custom Python functions
- 🎯 Simple configuration - Just add settings to your Django configuration
- 🧪 Well-tested - Comprehensive test suite with high coverage
- 📝 Type-safe - Full type hints for better IDE support
Installation
Using pip
pip install django-setup-tools
Using Poetry
poetry add django-setup-tools
Django Configuration
Add django_setup_tools to your INSTALLED_APPS in settings.py:
INSTALLED_APPS = [
# ... your other apps
'django_setup_tools',
]
Quick Start
1. Basic Configuration
Add the setup configuration to your Django settings:
# settings.py
DJANGO_SETUP_TOOLS = {
"": { # Default configuration (applies to all environments)
"on_initial": [
# These run only when the database is first initialized
("makemigrations", "--no-input"),
("migrate", "--no-input"),
("createsuperuser", "--no-input", "--username=admin", "--email=admin@example.com"),
],
"always_run": [
# These run every time the setup command is executed
("migrate", "--no-input"),
"django_setup_tools.scripts.sync_site_id", # Custom function
],
}
}
# Required for sync_site_id script
SITE_ID = 1
SITE_DOMAIN = "your-domain.com"
SITE_NAME = "Your Site Name"
2. Run the Setup Command
python manage.py setup
This will:
- Check if the database is initialized
- Run
on_initialscripts if it's the first time - Always run
always_runscripts
Environment-Specific Configuration
You can configure different behaviors for different environments:
# settings.py
DJANGO_SETUP_TOOLS_ENV = "development" # or "staging", "production", etc.
DJANGO_SETUP_TOOLS = {
"": { # Default configuration
"on_initial": [
("makemigrations", "--no-input"),
("migrate", "--no-input"),
],
"always_run": [
("migrate", "--no-input"),
],
},
"development": { # Development-specific
"on_initial": [
("loaddata", "dev_fixtures.json"),
],
"always_run": [
("collectstatic", "--no-input"),
],
},
"production": { # Production-specific
"on_initial": [
("createsuperuser", "--no-input", "--username=admin"),
],
"always_run": [
("collectstatic", "--no-input"),
("compress", "--force"),
],
},
}
Command Types
Django Management Commands
You can specify Django management commands in three formats:
DJANGO_SETUP_TOOLS = {
"": {
"always_run": [
"migrate", # Simple command
("migrate", "--no-input"), # Command with arguments (tuple)
["loaddata", "fixtures.json"], # Command with arguments (list)
],
}
}
Custom Python Functions
You can also call custom Python functions:
# myapp/scripts.py
def my_custom_setup(handler, *args):
"""Custom setup function."""
handler.stdout.write("Running custom setup...")
# Your custom logic here
handler.stdout.write("Custom setup completed!")
# settings.py
DJANGO_SETUP_TOOLS = {
"": {
"always_run": [
"myapp.scripts.my_custom_setup",
("myapp.scripts.my_custom_setup", "arg1", "arg2"), # With arguments
],
}
}
Custom functions receive:
handler: The management command instance (for output and styling)*args: Any additional arguments specified in the configuration
Built-in Scripts
Django Setup Tools includes many useful built-in scripts for common deployment and maintenance tasks:
Site Management
sync_site_id
Synchronizes the Django Site object with your settings:
# settings.py
SITE_ID = 1
SITE_DOMAIN = "yoursite.com"
SITE_NAME = "Your Site"
DJANGO_SETUP_TOOLS = {
"": {
"always_run": [
"django_setup_tools.scripts.sync_site_id",
],
}
}
Cache Management
clear_cache
Clears all Django cache backends:
DJANGO_SETUP_TOOLS = {
"": {
"always_run": [
"django_setup_tools.scripts.clear_cache",
],
}
}
Database Health
check_database_connection
Verifies database connectivity and reports basic information:
DJANGO_SETUP_TOOLS = {
"": {
"on_initial": [
"django_setup_tools.scripts.check_database_connection",
],
}
}
User Management
Django provides built-in support for creating superusers from environment variables. Simply use Django's built-in createsuperuser command with the --no-input flag:
# Set environment variables
export DJANGO_SUPERUSER_USERNAME=admin
export DJANGO_SUPERUSER_EMAIL=admin@yoursite.com
export DJANGO_SUPERUSER_PASSWORD=secure_password
DJANGO_SETUP_TOOLS = {
"": {
"on_initial": [
("createsuperuser", "--no-input"), # Uses environment variables automatically
],
}
}
Django automatically looks for these environment variables:
DJANGO_SUPERUSER_USERNAMEDJANGO_SUPERUSER_EMAILDJANGO_SUPERUSER_PASSWORD
Configuration Validation
verify_environment_config
Checks for required environment variables and Django settings:
DJANGO_SETUP_TOOLS = {
"": {
"always_run": [
"django_setup_tools.scripts.verify_environment_config",
],
}
}
check_static_files_config
Verifies static files configuration (STATIC_URL, STATIC_ROOT, etc.):
DJANGO_SETUP_TOOLS = {
"": {
"on_initial": [
"django_setup_tools.scripts.check_static_files_config",
],
}
}
Logging Setup
setup_log_directories
Creates log directories based on your Django logging configuration:
DJANGO_SETUP_TOOLS = {
"": {
"on_initial": [
"django_setup_tools.scripts.setup_log_directories",
],
}
}
Complete Example with Multiple Scripts
Here's a comprehensive example using multiple built-in scripts:
DJANGO_SETUP_TOOLS = {
"": {
"on_initial": [
"django_setup_tools.scripts.check_database_connection",
"django_setup_tools.scripts.setup_log_directories",
("createsuperuser", "--no-input"), # Uses environment variables automatically
("makemigrations", "--no-input"),
("migrate", "--no-input"),
"django_setup_tools.scripts.sync_site_id",
],
"always_run": [
"django_setup_tools.scripts.verify_environment_config",
"django_setup_tools.scripts.check_static_files_config",
("migrate", "--no-input"),
("collectstatic", "--no-input"),
"django_setup_tools.scripts.clear_cache",
],
}
}
Advanced Usage
Error Handling
The setup command will stop execution if any script fails. You can see detailed error messages in the output.
Database Initialization Detection
The command automatically detects if the database has been initialized by checking for the Django migrations table. This ensures on_initial scripts only run once.
Custom Script Best Practices
When writing custom scripts:
def my_script(handler, *args):
"""
Example custom script with best practices.
Args:
handler: Django management command instance
*args: Additional arguments
"""
# Use handler for output with proper styling
handler.stdout.write(
handler.style.NOTICE("Starting custom script...")
)
try:
# Your logic here
result = do_something()
handler.stdout.write(
handler.style.SUCCESS(f"Script completed: {result}")
)
except Exception as e:
handler.stdout.write(
handler.style.ERROR(f"Script failed: {e}")
)
raise # Re-raise to stop execution
Running Tests
Install Development Dependencies
# Using Poetry
poetry install
# Or using pip
pip install -r requirements-dev.txt
Run Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=django_setup_tools
# Run specific test file
pytest tests/test_setup_command.py
# Run with verbose output
pytest -v
Test Structure
tests/
├── conftest.py # Pytest configuration
├── test_setup_command.py # Original setup command tests
├── test_setup_command_extended.py # Extended setup command tests
├── test_scripts.py # Tests for built-in scripts
└── test_integration.py # Integration tests
Development
Setting Up Development Environment
# Clone the repository
git clone https://github.com/your-username/django-setup-tools.git
cd django-setup-tools
# Install with Poetry
poetry install
# Or create virtual environment and install with pip
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -e .
pip install -r requirements-dev.txt
Code Quality
The project uses several tools for code quality:
# Format code
black .
# Check types
mypy src/
# Lint code
pylint src/
# Check imports
isort --check-only .
# Run all checks
tox
Configuration Reference
Settings
| Setting | Type | Default | Description |
|---|---|---|---|
DJANGO_SETUP_TOOLS |
dict | {} |
Main configuration dictionary |
DJANGO_SETUP_TOOLS_ENV |
str | "" |
Environment name for environment-specific configs |
SITE_ID |
int | Required for sync_site_id | Django site ID |
SITE_DOMAIN |
str | Required for sync_site_id | Site domain name |
SITE_NAME |
str | Required for sync_site_id | Site display name |
Configuration Structure
DJANGO_SETUP_TOOLS = {
"environment_name": { # Use "" for default
"on_initial": [
# Commands that run only on first database initialization
],
"always_run": [
# Commands that run every time
],
},
}
Examples
Development Environment
# settings/development.py
DJANGO_SETUP_TOOLS_ENV = "development"
DJANGO_SETUP_TOOLS = {
"": {
"on_initial": [
("makemigrations", "--no-input"),
("migrate", "--no-input"),
],
"always_run": [
("migrate", "--no-input"),
],
},
"development": {
"on_initial": [
("loaddata", "dev_users.json"),
("loaddata", "dev_data.json"),
],
"always_run": [
"django_setup_tools.scripts.sync_site_id",
],
},
}
Production Environment
# settings/production.py
DJANGO_SETUP_TOOLS_ENV = "production"
DJANGO_SETUP_TOOLS = {
"": {
"on_initial": [
("migrate", "--no-input"),
],
"always_run": [
("migrate", "--no-input"),
],
},
"production": {
"on_initial": [
("createsuperuser", "--no-input", "--username=admin"),
],
"always_run": [
("collectstatic", "--no-input", "--clear"),
("compress", "--force"),
"django_setup_tools.scripts.sync_site_id",
"myapp.deployment.clear_cache",
],
},
}
Troubleshooting
Common Issues
Q: Scripts are running every time instead of just on initial setup
A: Check that your database is properly configured and migrations table exists. The on_initial detection relies on Django's migration system.
Q: Custom function not found
A: Ensure the function path is correct and the module is importable. Use the full dotted path like myapp.scripts.my_function.
Q: Commands failing with strange errors
A: Check that all required Django apps are in INSTALLED_APPS and that the database is accessible.
Debug Mode
Enable debug output by setting Django's logging level:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django_setup_tools': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
Contributing
We welcome contributions! Please see our Contributing Guide for details.
Reporting Issues
Please report issues on GitHub Issues.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
See CHANGELOG.md for version history.
Credits
- Created by Sam Jennings
- Inspired by the need for declarative Django deployment scripts
- Built with ❤️ for the Django community
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_setup_tools-0.2.5.tar.gz.
File metadata
- Download URL: django_setup_tools-0.2.5.tar.gz
- Upload date:
- Size: 13.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee77b83aae4578b60cd6902beef488ff831418b62276f45a998c571ff24e084b
|
|
| MD5 |
ae13773a4e392cdec017d8ad7c121f9f
|
|
| BLAKE2b-256 |
34dc6ad7b5e79dd0f3fca223e4528c9a4741733c5bf38224957daa41b30e9c49
|
Provenance
The following attestation bundles were made for django_setup_tools-0.2.5.tar.gz:
Publisher:
on-release-main.yml on SamuelJennings/django-setup-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_setup_tools-0.2.5.tar.gz -
Subject digest:
ee77b83aae4578b60cd6902beef488ff831418b62276f45a998c571ff24e084b - Sigstore transparency entry: 440221764
- Sigstore integration time:
-
Permalink:
SamuelJennings/django-setup-tools@1f3e009844c9ab8bc8111f76eccb20ed5742ee1c -
Branch / Tag:
refs/tags/v0.2.5 - Owner: https://github.com/SamuelJennings
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
on-release-main.yml@1f3e009844c9ab8bc8111f76eccb20ed5742ee1c -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_setup_tools-0.2.5-py3-none-any.whl.
File metadata
- Download URL: django_setup_tools-0.2.5-py3-none-any.whl
- Upload date:
- Size: 11.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3158b6f846ff16a82128b5272bb63a4f178aa72529ef9df4261ad14fb24d67f3
|
|
| MD5 |
26494a0c0d4891c218ad98097ba2950a
|
|
| BLAKE2b-256 |
a1f442c55e9aefbda56f4e2f02b15140692fb7adc649c3b4b409fff17770baf6
|
Provenance
The following attestation bundles were made for django_setup_tools-0.2.5-py3-none-any.whl:
Publisher:
on-release-main.yml on SamuelJennings/django-setup-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_setup_tools-0.2.5-py3-none-any.whl -
Subject digest:
3158b6f846ff16a82128b5272bb63a4f178aa72529ef9df4261ad14fb24d67f3 - Sigstore transparency entry: 440221779
- Sigstore integration time:
-
Permalink:
SamuelJennings/django-setup-tools@1f3e009844c9ab8bc8111f76eccb20ed5742ee1c -
Branch / Tag:
refs/tags/v0.2.5 - Owner: https://github.com/SamuelJennings
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
on-release-main.yml@1f3e009844c9ab8bc8111f76eccb20ed5742ee1c -
Trigger Event:
push
-
Statement type: