django-tenants强制依赖PostgreSQL,因其底层完全基于CREATE SCHEMA和SET search_path实现租户隔离;MySQL无schema概念,SQLite不支持search_path,故无法运行。

必须用 PostgreSQL,其他数据库直接报错或隔离失效。 django-tenants 不是“支持 PostgreSQL”,而是 CREATE SCHEMA 和 SET search_path 这两个 PostgreSQL 原生能力构成了它整个租户隔离的底层基础。MySQL 的 database ≠ schema,SQLite 根本不认 search_path —— 任何试图绕过这个限制的配置,最终都会在 migrate_schemas 或查询时崩掉。
为什么 settings.py 里 DATABASES 的 ENGINE 必须是 django_tenants.postgresql_backend?
这不是可选项,是开关。Django 默认的 django.db.backends.postgresql 完全不知道 schema_name 是什么,也不会在连接后自动执行 SET search_path TO 'acme', public。只有 django_tenants.postgresql_backend 会在每次获取 connection 时注入 schema 切换逻辑。
- 漏配会导致所有查询都落在
publicschema,租户数据混在一起 - 即使你手动写
cursor.execute("SET search_path TO ..."),ORM 的save()、filter()仍会走默认路径 - psycopg3 用户需确认
django-tenants>=4.0.0,否则初始化时抛AttributeError: module 'psycopg' has no attribute 'extensions'
SHARED_APPS 和 TENANT_APPS 怎么分?分错就登录失败
这不是“哪些 App 要共享”的风格问题,而是迁移命令的执行依据。Django 会根据这两个列表决定把表建在哪:
-
SHARED_APPS:只在publicschema 创建(如auth.User、customers.Client) -
TENANT_APPS:只在租户 schema 创建(如sales.Invoice、invoicing.Item) - 常见错误:把
auth放进TENANT_APPS→ 每个租户都有自己的auth_user表 → 登录时查不到用户 → 404 或 500 -
customers(含Client模型)必须在SHARED_APPS,但不能出现在TENANT_APPS中
租户创建后,为什么访问 acme.localhost 报 400?
django-tenants 中间件靠 request.get_host() 匹配 domain_url 字段,不是靠 URL 路径。它不会 fallback,也不会模糊匹配。
立即学习“Python免费学习笔记(深入)”;
- 域名必须完全一致:
acme.localhost≠localhost:8000≠acme.example.com -
domain_url值必须加进ALLOWED_HOSTS,否则 Django 在中间件早期就返回 400 - 本地调试务必用
http://acme.localhost:8000,且 Nginx/Apache 需透传原始 Host 头(禁用underscores_in_headers off) - 运行
python manage.py migrate_schemas --shared后,再跑python manage.py migrate_schemas --tenant,否则租户 schema 里没表
最易被忽略的是:租户 schema 名称只能是小写 ASCII + 下划线,不能以数字开头,也不能含大写字母或连字符 —— schema_name="Acme" 或 "acme-2026" 都会让 CREATE SCHEMA 语句直接失败,错误信息藏在 PostgreSQL 日志里,而不是 Django 控制台。

















