django-tenants

3.10.1 · active · verified Mon Apr 13

Django-tenants is a Python library that enables multi-tenancy for Django applications by leveraging PostgreSQL schemas. It allows a single Django project instance to serve multiple customers (tenants), each with isolated data, a crucial feature for Software-as-a-Service (SaaS) platforms. The library automates schema switching based on request hostnames, ensuring data isolation and efficient resource utilization. It is actively maintained, with the current stable version being 3.10.1, and receives regular updates to support new Django and Python versions. [1, 6, 7]

Warnings

Install

Imports

Quickstart

This quickstart demonstrates the core steps for setting up `django-tenants`. It involves configuring your Django `settings.py` with `SHARED_APPS`, `TENANT_APPS`, `DATABASE_ROUTERS`, and `TenantMainMiddleware`. You then define your `TenantMixin` and `DomainMixin` models, run initial migrations for shared applications using `migrate_schemas --shared`, and finally create tenant instances, which automatically create and migrate their respective schemas. [5, 8, 12, 16]

import os
import django
from django.conf import settings
from django.core.management import call_command

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project_name.settings')
django.setup()

# Assuming you have an app 'customers' with Client (TenantMixin) and Domain (DomainMixin) models
# from customers.models import Client, Domain # Uncomment in your actual project

# --- Example of creating a public tenant (adapt to your models) ---
# In your settings.py:
# TENANT_MODEL = "customers.Client"
# TENANT_DOMAIN_MODEL = "customers.Domain"

# Create a dummy Client and Domain for demonstration if not already existing
# (In a real scenario, this would involve your actual Client and Domain models)
class MockClient(object):
    id = 1 # Dummy ID
    schema_name = 'public'
    name = 'Public Tenant'

class MockDomain(object):
    domain = 'localhost'
    tenant = MockClient()
    is_primary = True


print("1. Ensure settings are configured (SHARED_APPS, TENANT_APPS, MIDDLEWARE, DATABASE_ROUTERS).")
print("2. Run initial migrations for shared schema:")
try:
    # In a real project, this would be `call_command('migrate_schemas', '--shared')`
    # For this quickstart, we'll simulate output, as actual migration requires a full Django setup
    print("   Simulating: python manage.py migrate_schemas --shared")
    # call_command('migrate_schemas', '--shared', verbosity=0)
    print("   Shared schema migrations complete.")
except Exception as e:
    print(f"   Error during shared migrations (expected if not a full Django setup): {e}")

print("3. Create a tenant (e.g., in a Django shell or a management command):")
try:
    # Example of creating a tenant (replace with your actual Client/Domain models and logic)
    # tenant = Client(schema_name='tenant1', name='Tenant One', paid_until='2030-12-31', on_trial=False)
    # tenant.save() # This automatically creates and syncs the schema

    # domain = Domain()
    # domain.domain = 'tenant1.localhost'
    # domain.tenant = tenant
    # domain.is_primary = True
    # domain.save()

    print("   Simulating tenant creation:")
    print("   client = Client(schema_name='tenant1', name='Tenant One', ...)")
    print("   client.save() # Schema 'tenant1' created and migrated automatically")
    print("   domain = Domain(domain='tenant1.localhost', tenant=client, is_primary=True)")
    print("   domain.save()")
    print("   Tenant 'tenant1' created with domain 'tenant1.localhost'.")
except Exception as e:
    print(f"   Error during tenant creation (expected if not a full Django setup): {e}")

print("4. Access tenant-specific data via hostname (e.g., tenant1.localhost:8000).")
print("   The TenantMainMiddleware will automatically switch the database schema.")

view raw JSON →