django-service-urls 3.0 - configure django settings with url-strings

Release Notes: django-service-urls 3.0

django-service-urls is a Django settings helper that lets you configure
databases, caches, email, storages, and task backends via single URL strings
(e.g., postgres://user:pass@host/db or smtp://localhost).

Links

Highlights

Zero-config activation: django-service-urls now register itself and
loads automatically at Python startup.

Plugin system: Third-party packages can now register custom URL schemes
automatically via pyproject.toml entry_points section.
Just uv add/pip install a plugin package and its schemes are available
to be used without manual imports (plugins can also introduce entirely
new service types).

Breaking Changes

  • Dropped Django < 5.2 support. Minimum supported versions are now
    Django 5.2, 6.0, and main.
  • database+dt backend now maps to django_tasks_db.DatabaseBackend
    (was django_tasks.backends.database.DatabaseBackend). Install
    django-tasks-db.
  • rq+dt backend now maps to django_tasks_rq.RQBackend
    (was django_tasks.backends.rq.RQBackend). Install
    django-tasks-rq.
  • import django_service_urls.loads is no longer needed in entry points.
    The .pth file handles activation automatically. Existing imports still work
    (the patch is idempotent) but can be removed.

New Features

Plugin discovery via entry points

Third-party packages can register schemes by declaring an entry point in the
pyproject.toml using the name django_service_urls:

# Third-party pyproject.toml
[project.entry-points."django_service_urls"]
my_backend = "my_package.service_urls"

The entry point module uses the existing @service.register() pattern.
Plugins are auto-discovered at startup (thanks to the .pth auto-activation).

For advanced use, discover_plugins() is available as a public API:

from django_service_urls import discover_plugins
discover_plugins()

Changes

Redis cache backend

The redis cache backend was documented but not implemented

CACHES = {
    "default": "redis://localhost:6379/0?timeout=300#KEY_PREFIX=prod"
}
# Produces:
# {
#     "BACKEND": "django.core.cache.backends.redis.RedisCache",
#     "LOCATION": "redis://localhost:6379/0",
#     "TIMEOUT": 300,
#     "KEY_PREFIX": "prod",
# }

Supports single host, multiple hosts (redis://host1:6379,host2:6379/0),
passwords, and all query/fragment options.

Password redaction in UrlInfo repr

UrlInfo.__repr__() now masks the password field as ***,
preventing accidental credential exposure in logs and tracebacks.

Bug Fixes

  • Fixed double URL-decoding in database service. DatabaseService.config_from_url
    called parse.unquote() on values already decoded by parse_url().
    A password encoded as %2540 (literal %40) would be silently corrupted to @.

Compatibility

  • Python: 3.10, 3.11, 3.12, 3.13, 3.14
  • Django: 5.2, 6.0, main

Upgrading

Most users can upgrade with no changes. Check for:

  1. Django < 5.2: No longer supported. Upgrade Django first.
  2. import django_service_urls.loads: Can be removed from manage.py,
    wsgi.py, asgi.py, etc. The .pth file handles this automatically.
    Existing imports are harmless (the patch is idempotent).
  3. database+dt:// or rq+dt:// URLs: Install django-tasks-db and/or
    django-tasks-rq packages separately — the backends have been split from the main django-tasks package.
  4. Credentials with literal %XX: If you were working around the double-decoding
    bug (e.g., encoding %40 as %252540), you can now use the standard single encoding (%2540).