pypi django-tenants 4.0.0
v4.0.0

4 hours ago

Breaking changes

  • Subfolder tenants get a URLconf built for each tenant (#1067). This fixes subfolder tenants under ASGI (#820, #822), where the URL was resolved against the wrong tenant.
    • Removed from django_tenants.urlresolvers: TenantPrefixPattern, tenant_patterns() and get_dynamic_tenant_prefixed_urlconf().
    • get_subfolder_urlconf() now returns a module rather than a dotted path. A get_urlconf() override that returns a string still works.
    • Custom handler400, handler403, handler404 and handler500 on the root URLconf are used for subfolder tenants. A 404 in a subfolder tenant whose root URLconf has no handler404 no longer errors.
  • schema_exists() compares names exactly by default (#1251). PostgreSQL schema names are case sensitive, so "C2" and "c2" are two schemas. If your code relied on the old case-insensitive match, for instance to check whether a name would collide with an existing schema, pass case_sensitive=False.
  • Adding a tenant whose schema name differs only in case from an existing tenant's is refused with a ValidationError (#1251). Existing tenants that already collide are left alone.
  • Migration output is prefixed with the schema even when it isn't going to a terminal (#1216, via #1273). CI logs, Docker logs and files now get the prefix, and the schema_migrate_message signal is now sent for that output. "Applying x..." appears while a migration runs, and its " OK" stays on the same line.

Fixes

  • clone_schema handles a partial unique index in a schema whose name needs quoting, such as one containing a hyphen. Before, it failed with syntax error at or near "TABLESPACE" (#1270).
  • With TENANT_LIMIT_SET_CALLS, the cached search_path is cleared on a savepoint rollback. PostgreSQL reverts the path on the rollback, so the connection could otherwise read another tenant's rows (#1263).
  • The search_path is set the same way on psycopg2 and psycopg3, and is cleared on rollback and close (#1249).
  • create_tenant stops with the reason when the tenant or domain can't be saved, instead of clearing everything and asking again for ever (#1194).
  • delete_tenant deletes the tenant when you confirm the prompt (#1252).
  • all_tenants_command works; before, every call raised NotImplementedError (#1253).
  • A FakeTenant without a domain_subfolder no longer raises an AttributeError (#1272, from #1031).
  • TenantRequestFactory sets request.tenant.domain_url from the request's host (#1132).

Features

  • TENANT_MULTIPROCESSING_MAX_TASKS_PER_CHILD recycles the multiprocessing executor's workers. A worker is replaced after this many tasks, which is this setting × TENANT_MULTIPROCESSING_CHUNKS tenants (#1227).
  • Multi-type tenants can clone from a template of their own type, named in TENANT_TYPES[type]['BASE_SCHEMA'] (#1265, #533).

Documentation

  • Notes on using django-tenants securely (#1266).

Dependencies

  • psycopg can now be any version below 3.4 (#1208).
  • Development dependency updates: docutils, gunicorn and others.

Thanks to everyone who contributed: @RJPercival, @Amirshox, @bishnusyangja, @dexbleeker, @hexponent, @pranaysai27, @McDonnellJoseph and @BasVerlooy.

Don't miss a new django-tenants release

NewReleases is sending notifications on new releases.