如何实现Django Rest Framework、Django Tenants与React协同工作
问题根因
报错来自两个配置问题,和JWT认证没有关系:
- 租户识别逻辑未触发:
TenantMainMiddleware是通过请求的Host头匹配Domain表记录识别租户的,你当前前端的请求目标地址是http://localhost:8000,后端收到的Host头值为localhost:8000,匹配不到cbd子域名对应的租户,请求会默认落到public共享schema。而company属于TENANT_APPS,它的数据表只在各业务租户的独立schema下创建,public schema中不存在company_project表,自然触发 relation 不存在的错误。注意:Origin头仅用于跨域校验,django-tenants不会读取这个字段识别租户。 - QuerySet 求值时机错误:你把
Project.objects.all()直接定义为ViewSet的类属性,这段代码会在Django启动加载类时就执行,此时完全没有请求上下文,也不存在激活的租户环境,就算域名配置正确,这里的查询也会连接到错误的schema。
修复方案
按以下顺序调整配置即可:
- 修正前端请求地址:将前端API请求的目标地址从
http://localhost:8000改为对应租户的子域名地址,比如测试cbd租户时用http://cbd.localhost:8000,保证后端收到请求时Host头携带正确的子域名信息。如果本地开发用了Vite/Webpack代理,需要配置代理转发时保留原始Host头,不要默认覆写为localhost。 - 调整ViewSet查询集逻辑:删除类属性位置的固定
queryset定义,重写get_queryset方法,在请求进入、租户上下文已经被中间件激活后再执行数据库查询。修改后的api/v1/project.py代码如下:
# 其他原有导入保持不变 from company.models import Project from rest_framework import serializers from rest_framework import viewsets from rest_framework import permissions class ProjectSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Project fields = ['url', 'name', 'keycode'] class ProjectViewSet(viewsets.ModelViewSet): serializer_class = ProjectSerializer permission_classes = [permissions.AllowAny] def get_queryset(self): # 方法执行时中间件已经完成schema切换,查询会自动命中当前租户的表 return Project.objects.all().order_by('id')
- 校验迁移状态:依次执行以下命令,确保所有schema下的迁移都正确同步:
python manage.py migrate_schemas --shared同步共享应用迁移python manage.py migrate_schemas同步所有租户schema下的租户应用迁移
如果后续有特殊场景需要手动调用tenant_context,可以直接从请求对象里取当前已识别的租户:self.request.tenant,不需要额外查库获取。
内容的提问来源于stack exchange,提问作者Dallas Caley
相关产品推荐
相关产品推荐

