Skip to content

Provisioning

django_db_tenants.provisioning creates, migrates and drops tenant databases at runtime. provision_tenant, migrate_tenants and the admin action are built on it. The database work is delegated to the client's database strategy.

Function Effect
create_database(client, if_not_exists=True) client.get_db_strategy().create_database(...). Returns True when the database was created. With the built-in strategy, an existing PostgreSQL database returns False, or raises RuntimeError with if_not_exists=False; MySQL raises the server's error with if_not_exists=False
migrate_tenant(client, **options) Registers the alias and runs migrate --database=<slug> non-interactively; options go to migrate (fake, verbosity, ...)
provision(client, create_db=True, migrate=True, activate=True) Create, migrate, then status active. Safe to re-run
drop_database(client) Closes the current thread's connection to the tenant and unregisters its alias, then client.get_db_strategy().drop_database(). The client row is not changed: delete it or set its status yourself

How each backend is handled by the built-in TemplateOverlay strategy is described in Database strategies. The connecting account needs the right to create and drop databases (CREATEDB on PostgreSQL, CREATE and DROP on MySQL).

Dropping a database in use

drop_database() closes only the calling thread's connection. Other processes or threads still connected to the tenant make PostgreSQL refuse the DROP. Suspend the client first, and wait for connections to close (CONN_MAX_AGE).

Example: provisioning in a background job

from django_db_tenants.models import Client
from django_db_tenants.provisioning import provision


@shared_task
def onboard(slug):
    client = Client.objects.using("default").get(slug=slug)
    provision(client)

Example: offboarding

from django_db_tenants.provisioning import drop_database

client.status = Client.Status.SUSPENDED
client.save()
drop_database(client)
client.delete()

django_db_tenants.provisioning

Create, migrate and drop tenant databases at runtime.

The database work itself is done by the client's database strategy (client.db_strategy, see strategies.py).

create_database

create_database(
    client: Client, if_not_exists: bool = True
) -> bool

Create the tenant's database through its strategy. Returns True if it was created.

drop_database

drop_database(client: Client) -> None

Drop the tenant's database through its strategy, after closing this thread's connection to it.

The client row is left alone: delete it, or set it back to PROVISIONING, yourself.

migrate_tenant

migrate_tenant(client: Client, **options) -> None

provision

provision(
    client: Client,
    create_db: bool = True,
    migrate: bool = True,
    activate: bool = True,
) -> Client

Full onboarding: create DB, migrate, mark ACTIVE. Safe to re-run.