每个请求一个数据库:基于用户的动态多租户路由器
实现租户感知的数据库路由器,根据请求中的域名或JWT声明动态切换读/写数据库,支持物理隔离的schema。 · 难度:入门 · +10XP
租户感知路由器
传统多租户教程只演示settings.DATABASES静态配置。本教程从中间件入手,在请求到达前解析租户ID并注入thread-local;然后编写DatabaseRouter类,通过检查当前租户的数据库别名来决定model所属数据库。同时处理migration时的跨库依赖,并支持备用数据库故障转移。你还能学到如何用上下文管理器临时覆盖路由策略。
class TenantRouter:
def db_for_read(self, model, **hints):
tenant_id = get_current_tenant_id()
return f'tenant_db_{tenant_id}'
def allow_migrate(self, db, app_label, model_name=None, **hints):
return db.startswith('tenant_db_')
# 中间件
class TenantMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
subdomain = request.get_host().split('.')[0]
set_current_tenant_id(subdomain)
return self.get_response(request)