python / expert
Snippet
Dynamic Multi-Tenant Database Routing via Thread-Local Context
This snippet demonstrates multi-tenant isolation in Django using a thread-local context and a custom database router. By setting the active database key on `threading.local()`, read and write queries are dynamically routed to specific tenant databases without modifying model queries.
snippet.py
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import threadingfrom django.db import models_tenant_context = threading.local()def set_current_tenant_db(db_name: str):_tenant_context.db_name = db_namedef get_current_tenant_db() -> str | None:return getattr(_tenant_context, 'db_name', None)class TenantDatabaseRouter:def db_for_read(self, model, **hints):return get_current_tenant_db() or 'default'def db_for_write(self, model, **hints):return get_current_tenant_db() or 'default'def allow_relation(self, obj1, obj2, **hints):return Truedef allow_migrate(self, db, app_label, model_name=None, **hints):return True
django
Breakdown
1
_tenant_context = threading.local()
Creates thread-isolated storage for tenant database keys to prevent cross-request leakage in multithreaded servers.
2
class TenantDatabaseRouter:
Defines a custom router class configured in settings.DATABASE_ROUTERS to handle routing logic.
3
return get_current_tenant_db() or 'default'
Dynamically selects the active tenant database from the thread-local state for query routing.