Skip to main content

HTTP + WebSocket middleware for multi-tenant Django projects

Project description

django-multitenant-middleware

django-multitenant-middleware is a Django package that provides multi-tenant support for both HTTP and WebSocket (Channels) requests. It resolves tenants dynamically based on subdomains, hostnames, or custom headers.


Installation

pip install django-multitenant-middleware

Settings Configuration (HTTP)

  1. Define your tenant model in settings.py:
CHANNELS_MULTITENANT_TENANT_MODEL = "tenants.Client"  ## your tenant model

# Optional: Custom resolver class and args
CHANNELS_MULTITENANT_RESOLVER_CLASS = None  # defaults to FlexibleSubdomainTenantResolver
CHANNELS_MULTITENANT_RESOLVER_ARGS = {"base_domain": BASE_DOMAIN}
  1. Add the middleware to your Django MIDDLEWARE list:
MIDDLEWARE = [
    # Other middleware...
    "django_multitenant_middleware.http_middleware.TenantHTTPMiddleware",
]

The middleware automatically sets request.tenant and request.tenant_context.


WebSocket Integration (ASGI)

  1. In asgi.py:
import os
import django
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application

from django_multitenant_middleware.ws_middleware import TenantWebSocketMiddleware
from django_multitenant_middleware.resolvers import FlexibleSubdomainTenantResolver
  1. Setup ASGI:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings") ## your django settings
django.setup()
django_asgi_app = get_asgi_application()
  1. Configure tenant resolver:
resolver = FlexibleSubdomainTenantResolver(
    base_domain="app.example.com",  # your base domain
    separators=("-", ".")
)
  1. Wrap WebSocket routes:
application = ProtocolTypeRouter({
    "http": django_asgi_app,
    "websocket": TenantWebSocketMiddleware(
        AuthMiddlewareStack(
            URLRouter(websocket_urlpatterns)
        ),
        tenant_model=Client,  # your tenant model
        resolver=resolver,
    ),
})

Tenant Resolvers

  • FlexibleSubdomainTenantResolver: Extracts tenant from subdomain prefixes Example: tenant1-app.example.com → tenant1

  • HeaderTenantResolver: Extracts tenant from a custom HTTP header Example: X-Tenant-ID: tenant1 → tenant1

  • Custom Resolver: Subclass BaseTenantResolver to implement your logic

from channels_multitenant.resolvers import BaseTenantResolver

class MyCustomResolver(BaseTenantResolver):
    def resolve(self, scope) -> str | None:
        # Implement your custom logic
        return "my_tenant"

TenantFetcher (Optional Helper)

TenantFetcher provides async caching for WebSocket tenants:

from channels_multitenant.tenant_fetcher import TenantFetcher
from tenants.models import Client # your tenant model

fetcher = TenantFetcher(Client)
tenant = await fetcher.get_tenant("tenant1")
  • Caches tenants (default 5 minutes)
  • Async-ready for Channels

Notes

  • Ensure CHANNELS_MULTITENANT_TENANT_MODEL points to your tenant model.
  • Missing or invalid settings will raise ImproperlyConfigured.
  • Compatible with Django 4.x+ and Channels 3.x+.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_multitenant_middleware-0.1.3.tar.gz (7.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file django_multitenant_middleware-0.1.3.tar.gz.

File metadata

File hashes

Hashes for django_multitenant_middleware-0.1.3.tar.gz
Algorithm Hash digest
SHA256 fe9c19cc70dd44affd2ef4316e8aba5d19ca0a1634f83534f5213f3333695f1c
MD5 ce8082344524dfa657e10a2b919f6dae
BLAKE2b-256 f5460d3bef849389f5477ec38400233002159165dd52a0d38e053516738b059a

See more details on using hashes here.

File details

Details for the file django_multitenant_middleware-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for django_multitenant_middleware-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 29858a1c31f4f3287c60da8c7980bc8eac7a64bad2971aef70cc6ae51119396d
MD5 565b8ac68ce5da1d8d81724ce5ed2cd8
BLAKE2b-256 ca607cdc87b02f1c421ba747c4446d7ddd8d63d81f627c22a1aa0593cd7eb552

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page