You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在django-tenants项目中独立部署DRF API至专属域名?

基于django-tenants的独立域名DRF API配置方案

一、核心配置步骤

1. 域名路由分离

使用django-hosts实现不同域名绑定不同路由配置,让api.example.com指向独立的API路由:

  • 安装依赖:pip install django-hosts
  • 在项目settings.py中添加配置:
    INSTALLED_APPS = [
        # 其他应用
        'django_hosts',
        'rest_framework',
    ]
    
    MIDDLEWARE = [
        'django_hosts.middleware.HostsRequestMiddleware',  # 放在最前面
        # 其他中间件(包括django-tenants的中间件)
        'django_hosts.middleware.HostsResponseMiddleware',  # 放在最后
    ]
    
    ROOT_HOSTCONF = 'your_project.hosts'
    DEFAULT_HOST = 'tenant'  # 租户子域名的默认路由
    PARENT_HOST = 'example.com'
    
  • 创建项目根目录下的hosts.py:
    from django_hosts import patterns, host
    
    host_patterns = patterns('',
        # 绑定api.example.com到api_urls路由
        host(r'api', 'your_project.api_urls', name='api'),
        # 绑定租户子域名(如tenant1.example.com)到tenant_urls路由
        host(r'(?P<tenant>[\w-]+)', 'your_project.tenant_urls', name='tenant'),
    )
    
  • 分别创建api_urls.py(存放DRF API路由)和tenant_urls.py(存放租户应用路由):
    api_urls.py示例:
    from django.urls import path
    from rest_framework import routers
    from .api_views import YourModelViewSet
    
    router = routers.DefaultRouter()
    router.register(r'your-model', YourModelViewSet)
    
    urlpatterns = router.urls
    

2. 跳过租户中间件处理

修改django-tenants的租户识别中间件,让api.example.com跳过自动租户识别:

  • 自定义中间件继承TenantMainMiddleware:
    from tenant.middleware.main import TenantMainMiddleware
    
    class CustomTenantMiddleware(TenantMainMiddleware):
        def process_request(self, request):
            if request.get_host() == 'api.example.com':
                # 跳过自动租户识别,留空让API自行处理
                request.tenant = None
                return None
            # 其他域名走原有租户识别逻辑
            return super().process_request(request)
    
  • 在settings.py中替换原有中间件:
    MIDDLEWARE = [
        'django_hosts.middleware.HostsRequestMiddleware',
        # 替换为自定义中间件
        'your_project.middleware.CustomTenantMiddleware',
        # 其他中间件
        'django_hosts.middleware.HostsResponseMiddleware',
    ]
    

3. API手动识别租户

由于API不在租户子域名下,需要通过其他方式识别租户,常用两种方案:

方案A:请求头传递租户标识

添加API专用中间件,从请求头获取租户信息并切换数据库连接:

from django.http import HttpResponseBadRequest
from tenant.models import Tenant
from tenant_schemas.utils import connection

class APITenantMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if request.get_host() == 'api.example.com':
            # 从请求头获取租户域名或ID
            tenant_domain = request.META.get('HTTP_X_TENANT_DOMAIN')
            if not tenant_domain:
                return HttpResponseBadRequest("Missing X-Tenant-Domain header")
            
            try:
                tenant = Tenant.objects.get(domain_url=tenant_domain)
                # 切换到租户的数据库schema
                connection.set_tenant(tenant)
                request.tenant = tenant
            except Tenant.DoesNotExist:
                return HttpResponseBadRequest("Invalid tenant domain")
        
        response = self.get_response(request)
        return response

将该中间件添加到settings.py的MIDDLEWARE中,放在CustomTenantMiddleware之后。

方案B:认证Token关联租户

扩展DRF的Token模型,让Token与租户绑定,认证后自动识别租户:

from rest_framework.authtoken.models import Token
from django.db import models
from tenant.models import Tenant

class TenantToken(Token):
    tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='tokens')

在DRF的认证视图或自定义认证类中,通过Token获取关联的租户并切换连接。

二、业内常见实践

  • 独立域名+请求头识别:最主流的方案,实现简单,客户端只需在请求时携带X-Tenant-Domain或X-Tenant-ID头,适合中小规模多租户系统。
  • API网关路由:通过Nginx、Kong等网关,根据请求头或路径前缀将请求转发到对应租户的逻辑层,适合高流量、复杂架构的系统,可实现负载均衡和权限统一管控。
  • 共享租户隔离:创建一个专门的"公共租户"存放API服务,但需严格区分公共数据与租户数据,容易引发数据混淆,仅适合特定场景。
  • API独立部署:将DRF API作为单独服务部署,与租户应用分离,通过内部接口调用租户服务,适合API流量大、需要独立扩容的场景,但会增加运维成本。

内容的提问来源于stack exchange,提问作者Crisp Apples

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 18:43:22