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.4.tar.gz (7.7 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.4.tar.gz.

File metadata

File hashes

Hashes for django_multitenant_middleware-0.1.4.tar.gz
Algorithm Hash digest
SHA256 a0130cba2e60c278ef795e0250b9b98f784dd6c5760fffe2de1f543c06ebd2fb
MD5 d6ba055ea43567bb4d7035e34089bbee
BLAKE2b-256 4fe493b0f9eb9dd2276d199e610d492eecee9b2851396e69c0ba06163f17457e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for django_multitenant_middleware-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ccb9055121874264a3c02b5297cda2f11db5dcb012a1857df85d3cc36fae394c
MD5 93b78ef36aa2a6222cc51c6e16b873ed
BLAKE2b-256 f4aa83bf191042b326fb84d186bbedb8196a62f33daf16a5eabad93003a61157

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