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

基于django-tenent-scheme创建独立租户管理门户的技术咨询

基于django-tenant-schemas实现独立租户管理门户的方案

不需要新建独立项目,完全可以在现有django-tenant-schemas项目内实现不与租户共享的管理门户,核心是区分主域名(门户)和子域名(租户)的路由逻辑,解决你之前门户在所有租户可见的问题。以下是具体实现步骤:

1. 配置域名识别与路由分离

django-tenant-schemas默认通过public租户处理公共内容,但我们可以通过自定义中间件,根据请求域名切换不同的URL配置:

1.1 编写域名识别中间件

在项目中创建中间件文件(比如middleware/tenant_domain_middleware.py):

from django.conf import settings
from django.urls import set_urlconf

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

    def __call__(self, request):
        # 提取不带端口的域名
        host = request.get_host().split(':')[0]
        # 判断是否是主门户域名
        if host == settings.MAIN_PORTAL_DOMAIN:
            # 加载公共门户的URL配置
            set_urlconf('your_project.public_urls')
        else:
            # 加载租户专属的URL配置
            set_urlconf('your_project.tenant_urls')
        
        response = self.get_response(request)
        return response

1.2 配置settings.py

  • 添加主域名常量:
MAIN_PORTAL_DOMAIN = "myapp.net"
  • 将自定义中间件加入中间件列表(注意要放在django_tenants.middleware.main.TenantMainMiddleware之后):
MIDDLEWARE = [
    # ...其他中间件
    'django_tenants.middleware.main.TenantMainMiddleware',
    'your_project.middleware.tenant_domain_middleware.DomainRoutingMiddleware',
    # ...其他中间件
]

1.3 分离路由文件

  • 创建public_urls.py:存放门户相关路由(注册、账户管理、许可证购买等),示例:
from django.urls import path
from .views import portal_home, client_register, account_management

urlpatterns = [
    path('portal/', portal_home, name='portal_home'),
    path('portal/register/', client_register, name='client_register'),
    path('portal/account/', account_management, name='account_management'),
    # ...其他门户路由
]
  • 创建tenant_urls.py:存放租户专属的业务路由,示例:
from django.urls import path
from .tenant_views import tenant_dashboard, tenant_profile

urlpatterns = [
    path('', tenant_dashboard, name='tenant_dashboard'),
    path('profile/', tenant_profile, name='tenant_profile'),
    # ...其他租户业务路由
]

2. 实现门户的租户创建逻辑

在公共视图中处理客户注册,直接操作Tenant和Domain模型创建新租户,示例:

from django.shortcuts import render, redirect
from django_tenants.models import Tenant, Domain
from .forms import ClientRegistrationForm

def client_register(request):
    if request.method == 'POST':
        form = ClientRegistrationForm(request.POST)
        if form.is_valid():
            # 创建租户(schema名称要符合数据库规范,建议小写、无特殊字符)
            tenant_schema = form.cleaned_data['client_name'].lower().replace(' ', '_')
            tenant = Tenant.objects.create(
                name=form.cleaned_data['client_name'],
                schema_name=tenant_schema,
                # 可添加其他自定义字段,比如许可证类型
                license_type=form.cleaned_data['license_type']
            )
            # 创建租户对应的子域名
            Domain.objects.create(
                tenant=tenant,
                domain=f"{tenant_schema}.myapp.net",
                is_primary=True
            )
            # 注册完成后跳转至租户登录页或门户首页
            return redirect('portal_home')
    else:
        form = ClientRegistrationForm()
    return render(request, 'portal/register.html', {'form': form})

3. DNS与服务器配置

不需要分开部署服务器,只需要将主域名和泛域名指向同一服务器IP:

  • myapp.net A记录 -> 你的服务器IP
  • *.myapp.net A记录 -> 你的服务器IP

如果用Nginx做反向代理,配置示例如下:

server {
    listen 80;
    server_name myapp.net *.myapp.net;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

关键注意事项

  • 门户的视图和路由仅在主域名下生效,子域名请求会加载租户专属路由,不会看到/portal路径
  • 所有门户操作都在public schema下执行,不需要切换租户上下文,避免与租户数据混淆
  • 若之前已将门户放在租户路由中,需彻底移除相关代码,确保仅在public_urls.py中定义门户路由

内容的提问来源于stack exchange,提问作者Mrugała Tomasz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 00:22:48