A Django app to allow multi-tenancy.
Project description
django-omnitenant
Multi-tenancy made simple for Django applications!
๐ Overview
django-omnitenant is a powerful, flexible multi-tenancy solution for Django that allows you to efficiently manage multiple isolated tenants within a single Django application. Whether you're building a SaaS platform, a shared hosting environment, or a complex multi-tenant application, django-omnitenant provides the tools you need to handle tenant isolation at the database, schema, or hybrid level.
Key Features
- โ Flexible Tenant Isolation โ Choose between database-per-tenant, schema-per-tenant, or hybrid isolation strategies(Coming soon...)
- โ Automatic Tenant Context โ Seamlessly switch between tenants with context managers
- โ Admin Restrictions โ Restrict admin access to tenant-specific models
- โ Tenant-Aware Middleware โ Automatically resolve tenants from HTTP requests
- โ Tenant-Aware Caching โ Cache keys prefixed with tenant IDs
- โ Tenant-Aware Celery โ Run Celery tasks in the context of a specific tenant
- โ Comprehensive CLI Tools โ Create, manage, and migrate tenants with ease
- โ Signal System โ Hook into tenant lifecycle events (creation, deletion, migration)
- โ Customizable Tenant Resolution โ Resolve tenants from subdomains, custom domains, or other sources
โจ Features
Multi-Tenancy Strategies
- Database-per-Tenant: Each tenant has its own database
- Schema-per-Tenant: All tenants share a single database but have separate schemas
- Hybrid(soon...): Combine database and schema isolation for complex scenarios
Tenant Management
- Create, delete, and manage tenants with a simple CLI
- Run migrations for individual tenants or all tenants at once
- Create superusers within specific tenants
Tenant-Aware Components
- Middleware: Automatically resolves tenants from HTTP requests
- Database Router: Routes queries to the correct database/schema
- Cache Backend: Prefixes cache keys with tenant IDs
- Celery Integration: Run tasks in the context of a specific tenant
Security & Permissions
- Restrict admin access to tenant-specific models
- Ensure tenant isolation at the database and schema level
- Validate tenant IDs and domain names
Extensible Architecture
- Custom tenant models and domain models
- Custom tenant resolvers for flexible tenant resolution logic
- Patch system for extending Django's core functionality
๐ ๏ธ Tech Stack
- Language: Python 3.8+
- Framework: Django 3.2+
- Database: PostgreSQL (recommended), MySQL(only for db type isolation)
- Dependencies: Django, psycopg2 (for PostgreSQL), Celery (optional)
- License: MIT
๐ฆ Installation
Prerequisites
Before installing django-omnitenant, ensure you have the following:
- Python 3.8 or higher
- Django 3.2 or higher
- PostgreSQL (recommended) or another supported database
- Basic familiarity with Django and Python
Quick Start
- Install django-omnitenant:
pip install django-omnitenant
- Add to your
INSTALLED_APPS:
# settings.py
INSTALLED_APPS = [
...
'django_omnitenant',
...
]
- Configure django-omnitenant:
Add the following to your settings.py:
# settings.py
OMNITENANT_CONFIG = {
'TENANT_MODEL': 'myapp.Tenant', # Your custom tenant model
'DOMAIN_MODEL': 'myapp.Domain', # Your custom domain model
'PUBLIC_HOST': 'localhost', # Default public host
'PUBLIC_TENANT_NAME': 'public_omnitenant', # Default public tenant
'MASTER_TENANT_NAME': 'Master', # Master tenant name
'PATCHES': [
"your custom patches's full path"
],
}
- Run migrations:
python manage.py migrate
- Add middleware:
# settings.py
MIDDLEWARE = [
...
'django_omnitenant.middleware.TenantMiddleware',
...
]
- Configure your database router:
# settings.py
DATABASE_ROUTERS = [
'django_omnitenant.routers.TenantRouter',
]
- Create your first tenant:
python manage.py createtenantsuperuser --tenant-id=mytenant
๐ฏ Usage
Basic Usage
Creating a Tenant
python manage.py createtenant
Running Migrations for a Tenant
python manage.py migratetenant --tenant-id=mytenant
Running Migrations for All Tenants
python manage.py migratealltenants
Shell with Tenant Context
python manage.py shell --tenant-id=mytenant
Show All Tenants
python manage.py showtenants
Advanced Usage: Custom Tenant Model
- Define your tenant model:
# models.py
from django.db import models
from django_omnitenant.models import BaseTenant
class Tenant(BaseTenant):
description = models.TextField(blank=True, null=True)
- Configure django-omnitenant:
# settings.py
OMNITENANT_CONFIG = {
'TENANT_MODEL': 'myapp.Tenant',
...
}
Advanced Usage: Custom Tenant Resolver
- Create a custom resolver:
# resolvers/custom_resolver.py
from django_omnitenant.resolvers.base import BaseTenantResolver
from django_omnitenant.utils import get_tenant_model
class CustomTenantResolver(BaseTenantResolver):
def resolve(self, request):
# Implement your custom logic to resolve the tenant
tenant_id = request.GET.get('tenant_id')
Tenant = get_tenant_model()
return Tenant.objects.get(tenant_id=tenant_id)
- Configure the resolver:
# settings.py
OMNITENANT_CONFIG = {
'TENANT_RESOLVER': 'myapp.resolvers.CustomTenantResolver',
...
}
Advanced Usage: Tenant-Aware Admin
# admin.py
from django.contrib import admin
from django_omnitenant.admin import _TenantRestrictAdminMixin
class MyModelAdmin(_TenantRestrictAdminMixin, admin.ModelAdmin):
pass
admin.site.register(MyModel, MyModelAdmin)
๐ Project Structure
django-omnitenant/
โโโ __init__.py
โโโ admin.py
โโโ apps.py
โโโ bootstrap.py
โโโ conf.py
โโโ constants.py
โโโ exceptions.py
โโโ middleware.py
โโโ models.py
โโโ routers.py
โโโ signals.py
โโโ tenant_context.py
โโโ utils.py
โโโ validators.py
โโโ views.py
โโโ backends/
โ โโโ __init__.py
โ โโโ base.py
โ โโโ cache_backend.py
โ โโโ database_backend.py
โ โโโ postgresql/
โ โ โโโ __init__.py
โ โ โโโ base.py
โ โโโ schema_backend.py
โโโ management/
โ โโโ commands/
โ โโโ createtenant.py
โ โโโ createsuperuser.py
โ โโโ migratealltenants.py
โ โโโ migratetenant.py
โ โโโ shell.py
โ โโโ showtenants.py
โโโ patches/
โ โโโ cache.py
โ โโโ celery.py
โโโ resolvers/
โ โโโ __init__.py
โ โโโ base.py
โ โโโ customdomain_resolver.py
โ โโโ subdomain_resolver.py
โโโ tests/
โ โโโ testcases.py
โโโ migrations/
๐ง Configuration
Environment Variables
No environment variables are required, but you can customize django-omnitenant by setting the following in your settings.py:
# Database and Cache Configuration
MASTER_DB_ALIAS = 'default'
PUBLIC_DB_ALIAS = 'public'
MASTER_CACHE_ALIAS = 'default'
# Tenant Configuration
MASTER_TENANT_NAME = 'Master'
PUBLIC_TENANT_NAME = 'public_omnitenant'
DEFAULT_SCHEMA_NAME = 'public'
# Tenant Model Configuration
OMNITENANT_CONFIG = {
'TENANT_MODEL': 'myapp.Tenant',
'DOMAIN_MODEL': 'myapp.Domain',
'PUBLIC_HOST': 'localhost',
'PUBLIC_TENANT_NAME': 'public_omnitenant',
'MASTER_TENANT_NAME': 'Master',
'PATCHES': [
'django_omnitenant.patches.cache',
'django_omnitenant.patches.celery',
],
}
Customizing Tenant Models
To customize your tenant model, create a model that inherits from BaseTenant:
# models.py
from django.db import models
from django_omnitenant.models import BaseTenant
class Tenant(BaseTenant):
description = models.TextField(blank=True, null=True)
Customizing Domain Models
To customize your domain model, create a model that represents domains and link it to tenants:
# models.py
from django.db import models
from django_omnitenant.models import BaseTenant
class Domain(models.Model):
domain = models.CharField(max_length=255, unique=True)
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
def __str__(self):
return self.domain
๐ค Contributing
We welcome contributions from the community! Here's how you can contribute to django-omnitenant:
Development Setup
- Clone the repository:
git clone https://github.com/yourusername/django-omnitenant.git
cd django-omnitenant
- Create a virtual environment:
python -m venv venv
source venv/bin/activate # On Windows use `venv\Scripts\activate`
- Install dependencies:
pip install -e .
- Run tests:
python -m pytest tests/
Code Style Guidelines
- Follow PEP 8 style guidelines
- Use type hints where possible
- Write clear, concise, and well-documented code
- Ensure tests cover all functionality
Pull Request Process
- Fork the repository and create your branch from
master. - Make your changes and ensure they pass all tests.
- Submit a pull request with a clear description of your changes.
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ฅ Authors & Contributors
Maintainers:
- Krishna Rimal - Initial work and ongoing maintenance
Contributors:
- Contributors are welcomed
๐ Issues & Support
Reporting Issues
If you encounter any issues or have feature requests, please open an issue on the GitHub Issues page.
Getting Help
- Documentation: Check out the wiki for detailed guides.
- FAQ: Common questions and answers can be found in the FAQ section.
๐บ๏ธ Roadmap
Planned Features
- Hybrid Isolation: Combine database and schema isolation for more complex scenarios
- Tenant Analytics: Built-in tools for monitoring and analyzing tenant usage
- Tenant Provisioning API: RESTful API for programmatically creating and managing tenants
- Improved Documentation: More detailed guides and tutorials
Known Issues
- PostgreSQL 16 Compatibility: Testing and ensuring compatibility with PostgreSQL 15
- Celery Task Persistence: Improving task persistence across tenant switches
Future Improvements
- Better Performance: Optimize database and cache operations for better performance
- Enhanced Security: Additional security features and validations
- More Resolvers: Additional tenant resolution strategies
๐ Star and Share
If you find django-omnitenant useful, please consider giving it a star on GitHub! Sharing it with your network helps us reach more developers and continue improving the project.
Thank you for using django-omnitenant! ๐
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_omnitenant-0.2.2.tar.gz.
File metadata
- Download URL: django_omnitenant-0.2.2.tar.gz
- Upload date:
- Size: 28.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5e1acf91c3c547a0325533396c208f150adf198a64dd2de2467713abf333122
|
|
| MD5 |
5deb2dab36814faf5d1431637e36a1fb
|
|
| BLAKE2b-256 |
16a36e0842988bc559b5a8d02b1f23fd1afcb2aa953783e1001c64f998cf529b
|
File details
Details for the file django_omnitenant-0.2.2-py3-none-any.whl.
File metadata
- Download URL: django_omnitenant-0.2.2-py3-none-any.whl
- Upload date:
- Size: 35.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
443f79895cdf0602a1b44a4865adf4b67cda38b99b41e2d3b10623b2135d8ed7
|
|
| MD5 |
43da8b88381d604c39399b1a591269fe
|
|
| BLAKE2b-256 |
812cd81464cb2ef6f720612663efc2f9ddc2c2746a93f5732cfa8f7b20930cef
|