Registry / database / django-tenants

django-tenants

JSON →
library3.14.0pypypi✓ verified 24d ago

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]

pip install django-tenants
INSTALL
IMPORT
SIG · DJANGO-TENANTS
D
django-tenants
databasepythonv3.14.0
Install
3.5s avg
Import
Disk
67MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v3.14.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.000s · 67.6MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 3.5s · import 0.000s · 68MB
67MB installed
● package 67MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

TenantMixin
from django_tenants.models import TenantMixin
from django_tenants.models import TenantMixin

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.")
Debug
Known issues
breaking`django-tenants` v3.x has aligned with newer Django and Python versions. Specifically, v3.10.0 and v3.8.0 added support for Django 5.x and Python 3.13, while dropping support for older Django versions (e.g., 3.x, 4.0) and Python versions (e.g., 3.8, 3.1) in previous v3.x releases. Always check release notes for specific version compatibility when upgrading. [15]
fix
Review `django-tenants` release notes (e.g., GitHub releases) before upgrading to ensure compatibility with your Django and Python environment. Upgrade your Django and Python versions if necessary.
affects: 3.x onwards
breakingAs of v3.0.0, `django-tenants` removed `psycopg2` as a direct dependency. While this provides flexibility, it means users must explicitly install a PostgreSQL adapter like `psycopg2-binary` or `psycopg3` for database connectivity. [13]
fix
Explicitly install your preferred PostgreSQL adapter: `pip install psycopg2-binary` or `pip install "psycopg[binary]"` (for psycopg3).
affects: >=3.0.0
gotchaThe `auto_drop_schema` field on your `TenantMixin` model defaults to `False`. If you explicitly set it to `True`, deleting a tenant model instance through the ORM will *automatically drop its associated PostgreSQL schema* without further confirmation. This can lead to irreversible data loss. [3]
fix
Exercise extreme caution when setting `auto_drop_schema = True` on your tenant model. Understand the implications and ensure proper backup strategies or manual schema management if this flag is enabled.
affects: All versions
gotchaRunning the standard `python manage.py migrate` command will apply migrations to *both* shared and tenant schemas, which is often not the desired behavior. You must use `python manage.py migrate_schemas --shared` for shared apps and `python manage.py tenant_command migrate --schema=yourtenant` (or `all_tenants_command`) for tenant-specific apps. [5]
fix
Always use `migrate_schemas --shared` for shared applications and `tenant_command migrate` or `all_tenants_command` for tenant-specific applications. Do not use `manage.py migrate` directly after initial setup.
affects: All versions
gotchaFor `request.tenant` to be available in your templates, `django.template.context_processors.request` must be included in the `context_processors` option within your `TEMPLATES` setting in `settings.py`. [5]
fix
Ensure your `TEMPLATES` setting includes `'django.template.context_processors.request'` in the `'OPTIONS': {'context_processors': [...]}` list.
affects: All versions
gotchaWhen working with ASGI applications (e.g., Dpahne, Uvicorn) and custom tenant resolution logic outside of `TenantMainMiddleware`, relying on `thread_locals` or similar global state for tenant context can be problematic due to the asynchronous nature of ASGI servers. This can lead to incorrect tenant context being applied. [17]
fix
For ASGI applications, ensure tenant context is explicitly passed or managed within the async request/task scope. Prefer `schema_context` or `tenant_context` utilities for explicit context switching in non-request-bound operations.
affects: All versions (especially with ASGI)
Upgrade
Version history
3.14.0latest on PyPI · released Aug 5, 2026
Audit
Dependencies
DjangorequiredCore web framework dependency.
PostgreSQLrequiredDatabase backend required for schema-based multi-tenancy. [1]
psycopg2-binaryoptionalPostgreSQL adapter for Python. `django-tenants` no longer lists it as a direct requirement but it's necessary for database connectivity. `psycopg3` is also supported. [13, 15]
psycopg3optionalModern PostgreSQL adapter for Python. `django-tenants` no longer lists it as a direct requirement but it's necessary for database connectivity. `psycopg2-binary` is also supported. [13, 15]
Agent activity
21 hits · last 30 days
node
20
Resources
django-tenants — pip install django-tenants · libregistry