如何基于django_tenants和django_tenant_users实现多层级多租户SaaS架构?
实现基于django_tenants的多层级嵌套租户架构方案
结论:完全可行,但需要对django_tenants进行定制扩展,因为它原生仅支持单层级租户隔离。
以下是具体实现思路和方案:
1. 扩展Tenant模型,添加层级关联
django_tenants的AbstractTenant模型可以直接继承扩展,通过添加自关联字段实现树形层级结构:
from django.db import models from django_tenants.models import AbstractTenant, DomainMixin class Client(AbstractTenant): name = models.CharField(max_length=100) # 自关联父租户,允许为空(顶级租户无父级) parent_tenant = models.ForeignKey( 'self', on_delete=models.SET_NULL, null=True, blank=True, related_name='child_tenants' ) # 可添加其他业务字段,比如创建时间、状态等 class Domain(DomainMixin): pass
这个改动能让你在数据库层面存储租户的层级关系,后续所有租户的创建、查询都可以基于这个字段做层级过滤。
2. 定制Schema命名规则,体现层级
django_tenants依赖独立数据库schema实现租户隔离,你可以通过自定义schema名称来体现租户层级,方便后续管理和识别:
import uuid from django_tenants.utils import schema_exists def generate_child_schema_name(parent_schema): # 生成带父级标识的唯一schema名称 suffix = uuid.uuid4().hex[:4] schema_name = f"{parent_schema}_child_{suffix}" # 确保schema名称唯一 while schema_exists(schema_name): suffix = uuid.uuid4().hex[:4] schema_name = f"{parent_schema}_child_{suffix}" return schema_name # 创建子租户示例 parent_tenant = Client.objects.get(schema_name="client_xyz") child_tenant = Client( name="子部门A", parent_tenant=parent_tenant, schema_name=generate_child_schema_name(parent_tenant.schema_name) ) child_tenant.save() # 绑定域名等后续操作...
这种方式保留了django_tenants原生的schema隔离逻辑,无需修改核心源码,兼容性更好。
3. 调整权限与数据访问逻辑
多层级租户通常需要支持父租户访问子租户数据、子租户继承父租户配置等场景,你需要做以下调整:
- 跨Schema数据查询:使用django_tenants提供的
schema_context上下文管理器切换到目标租户的schema进行查询:
from django_tenants.utils import schema_context def get_child_tenant_data(parent_tenant): child_data = [] for child in parent_tenant.child_tenants.all(): with schema_context(child.schema_name): # 查询子租户下的业务数据 records = YourBusinessModel.objects.all() child_data.extend(list(records)) return child_data
- 用户权限控制:结合django_tenant_users,给父租户的用户添加访问子租户的权限,比如在创建子租户时自动关联父租户的管理员用户:
from tenant_users.tenants.models import TenantUser def assign_parent_user_to_child(child_tenant, parent_user): # 将父租户用户添加到子租户 tenant_user = TenantUser.objects.create( user=parent_user, tenant=child_tenant, is_active=True ) # 可添加角色权限等 return tenant_user
4. 关键注意事项
- 不要直接修改django_tenants或django_tenant_users的核心源码,尽量通过继承、信号、自定义管理器等方式扩展,避免后续版本升级出现冲突。
- 控制租户层级深度,过深的层级会增加Schema管理和数据查询的复杂度,建议限制在3-4层以内。
- 测试时覆盖多层级场景:创建嵌套租户、跨租户数据访问、权限隔离、Schema迁移等,确保逻辑稳定。
内容的提问来源于stack exchange,提问作者Adnan Nazir
相关产品推荐
相关产品推荐

