Expert guidance for Django multi-tenant SaaS projects with PostgreSQL, Redis, MinIO, and modern Python tooling (uv, pytest, Tailwind)
Expert guidance for working with Django-based multi-tenant SaaS applications following the nav/django-project-template architecture.
This skill provides comprehensive knowledge of a production-ready Django multi-tenant template with:
When setting up the project:
1. Run `make install` to bootstrap the entire environment (dependencies, Docker services, superuser, initial tenant)
2. If running individual setup steps:
- `make run/docker` for Docker services (PostgreSQL, Redis, MinIO)
- `uv sync` for Python dependencies
- `make migrations` and `make migrate` for database schema
- `uv run python src/manage.py createtenant` for additional tenants
Choose the appropriate server command:
When writing or running tests:
1. Use `make test` for full test suite
2. For specific files: `make test path=src/app/tests/test_models.py`
3. For specific methods: `uv run pytest src/app/tests/test_models.py::TestClassName::test_method`
4. Always use factory-boy for test data creation
5. Tests are organized in `src/*/tests/` directories following Django conventions
6. pytest-django handles test database creation automatically
Before committing code:
1. Run `uv run ruff check` to identify linting issues
2. Run `uv run ruff format` to auto-format code
3. Run `uv run pyright` for type checking
4. Configuration is in `pyproject.toml`
When modifying models:
1. Create migrations: `make migrations`
2. Apply migrations: `make migrate`
3. For complete database reset: `make db` (recreates with credentials)
4. PostgreSQL credentials are stored in `.pgpass` file
**CRITICAL:** Always consider tenant isolation when creating models or features.
1. **Tenant-scoped models** MUST inherit from `Tenanted` base class:
```python
from infrastructure.models import Tenanted
class MyModel(Tenanted):
# tenant field automatically added and managed
pass
```
2. **Global models** should NOT inherit from `Tenanted`:
- Configuration tables
- System-wide lookups
- Cross-tenant reference data
3. **Tenant routing** uses Django Sites framework:
- Each tenant has unique subdomain
- `Tenant` model links to `Site` model
- Domain-based routing handled automatically
4. **User-tenant relationships** via Membership system:
- Users can belong to multiple tenants
- Group-based permissions within tenants
Apply appropriate base classes for common patterns:
1. **`Audited`** - For automatic timestamp tracking:
```python
from infrastructure.models import Audited
class MyModel(Audited):
# created_at and updated_at auto-managed
pass
```
2. **`Deactivatable`** - For soft deletion:
```python
from infrastructure.models import Deactivatable
class MyModel(Deactivatable):
# is_active field + custom manager that filters deactivated
pass
```
3. **`UlidField`** - For primary keys with prefixes:
```python
from infrastructure.fields import UlidField
class MyModel:
id = UlidField(prefix="mdl_", primary_key=True, editable=False)
```
4. **Combining patterns:**
```python
class MyModel(Tenanted, Audited, Deactivatable):
id = UlidField(prefix="mdl_", primary_key=True, editable=False)
# Gets: tenant, created_at, updated_at, is_active
```
Organize code following the established app structure:
Each app follows Django conventions:
When extending functionality, leverage existing infrastructure:
1. **Authentication:**
- Custom `User` model in `tenant.models` inherits `AbstractUser`
- django-allauth configured for social login
- `LoginRequiredMiddleware` enforces global login requirement
- Exempt URLs via middleware configuration
2. **Storage:**
- MinIO/S3 via django-storages
- Configuration in settings for local vs production
- File uploads automatically handled
3. **Caching:**
- Redis configured for sessions and caching
- Use Django cache framework as normal
4. **Monitoring:**
- Prometheus metrics at `/metrics` endpoint
- Sentry error tracking (production only)
- Custom context processors for request context
5. **Static Files:**
- WhiteNoise serves static files in production
- Tailwind CSS for styling
- Run `make static` before deployment
Handle settings and environment properly:
1. Use environment variables for secrets and configuration
2. `.pgpass` file handles PostgreSQL authentication
3. `DEBUG` environment variable controls dev vs production mode
4. Docker Compose defines local development services
5. Settings provide sensible defaults for development
```python
from infrastructure.models import Tenanted, Audited, Deactivatable
from infrastructure.fields import UlidField
class Product(Tenanted, Audited, Deactivatable):
id = UlidField(prefix="prd_", primary_key=True, editable=False)
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=10, decimal_places=2)
class Meta:
ordering = ["-created_at"]
```
Then run:
```bash
make migrations
make migrate
```
```python
import factory
from tenant.tests.factories import TenantFactory
from myapp.models import Product
class ProductFactory(factory.django.DjangoModelFactory):
class Meta:
model = Product
tenant = factory.SubFactory(TenantFactory)
name = factory.Faker("word")
price = factory.Faker("pydecimal", left_digits=3, right_digits=2, positive=True)
```
```python
class CustomMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Pre-request logic
response = self.get_response(request)
# Post-request logic
return response
```
Register in `src/project/settings.py` `MIDDLEWARE` list.
1. **Always inherit from `Tenanted`** for tenant-specific models
2. **Use ULID fields** with appropriate prefixes for new models
3. **Follow soft deletion** patterns with `Deactivatable`
4. **Run migrations** after any model changes
5. **Write tests** using factory-boy for new features
6. **Run code quality tools** before committing
7. **Keep migration files** in version control (tracked in git)
8. **Use `uv` commands** instead of pip for dependency management
9. **Consider multi-tenant isolation** in all queries and views
10. **Environment variables** for configuration, not hardcoded values
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/django-multi-tenant-project-template/raw