Sheba ISP ERP is architected around strict shared-database, shared-schema multi-tenancy. All tenants coexist within a single PostgreSQL database and a single schema (public).
No Database-Per-Tenant: Under no circumstances shall database-per-tenant or schema-per-tenant routing be introduced.
Mandatory Foreign Key: Every tenant-scoped database model inherits from TenantScopedModel or explicitly defines tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, db_index=True).
A request's tenant identity is strictly resolved from the incoming domain or subdomain. Clients cannot override their tenant using request headers (X-Tenant-ID), query parameters (?tenant_id=), or request body fields.
class TenantScopedManager(models.Manager): def for_tenant(self, tenant): if not tenant: return self.none() tenant_id = tenant.id if hasattr(tenant, 'id') else tenant return self.filter(tenant_id=tenant_id)
In DRF ViewSets, get_queryset() consistently enforces tenant boundaries:
class BaseTenantViewSet(viewsets.ModelViewSet): def get_queryset(self): tenant = getattr(self.request, 'tenant', None) if not tenant: return self.queryset.none() return self.queryset.filter(tenant=tenant)