Fixes
Cloning a schema owned by a role whose name needs quoting (#1239, fixes #1189). Role names were interpolated into generated DDL raw, so a role containing a hyphen — or starting with a digit — made the statement a syntax error and the clone failed outright:
CREATE SCHEMA new_tenant AUTHORIZATION my-role
^ syntax error at or near "-"
Three places were affected: CREATE SCHEMA ... AUTHORIZATION, ALTER SEQUENCE ... OWNER TO, and the ALTER TABLE ... OWNER TO in pg_get_tabledef. Table and type owners were already quoted at their SELECT and are unchanged. This also resolves the long-standing #561, which was the same bug seen through a role name beginning with a digit.
STORAGES in the test project and examples (#1240, fixes #1095, #1173). DEFAULT_FILE_STORAGE and STATICFILES_STORAGE were deprecated in Django 4.2 and removed in 5.1, where they are silently ignored — but the test project and all three example tutorials still set them. Anyone who copied an example was quietly getting single-tenant file storage:
STORAGES['default']
| STORAGES['staticfiles']
| |
|---|---|---|
| before | FileSystemStorage
| StaticFilesStorage
|
| after | TenantFileSystemStorage
| TenantStaticFilesStorage
|
Nothing errored, which is why it went unnoticed. docs/files.rst now leads with STORAGES, keeping DEFAULT_FILE_STORAGE documented for Django < 4.2, which is still supported.
New
get_current_tenant() (#1241, closes #1217). get_tenant() takes a request, so there was no way to ask which tenant am I in from a helper function, a Celery task, or a signal handler:
from django_tenants.utils import get_current_tenant
def send_welcome_email(user):
tenant = get_current_tenant() # no request neededtenant_context() sets the real instance, so that is what comes back. schema_context() only ever knows a schema name, so a FakeTenant is returned there — read its schema_name, or use tenant_context() when you need the model.
Breaking
migrate_schemas no longer accepts --list / -l (#794). Nothing ever read the flag — Django moved that functionality to showmigrations long ago — so it silently did nothing. Passing it now raises unrecognized arguments rather than being accepted and ignored. Use showmigrations, or tenant_command showmigrations --schema=<name> for a single tenant.
Also
is_public_schema's unusedappargument is now optional, so both{% is_public_schema %}and{% is_public_schema app %}work (#339).- Regression test added for cloning inside
transaction.atomic()— fixed in 3.12.0 by #1150 but shipped without a test, so nothing preventedtransaction.commit()returning (#1155, #694).
Housekeeping
The issue tracker has had a thorough pass: 254 open issues down to 88. Everything closed carries a reason, and anything closed as stale can be reopened — if one of them is still biting you on 3.13.0, please do, ideally with the versions and steps to reproduce.
The missing v3.8.0 (#1156) and v3.10.1 (#1222) tags have also been created, pointing at the commits those releases were built from.
Full Changelog: v3.12.0...v3.13.0