Multi-Tenancy
We usedjango-tenants to implement multi-tenancy at the database schema level.
- Public Schema: Contains shared global data like
Client,Domain, and global settings. Access is made via the main domain (e.g.,example.com). - Tenant Schemas: Each school gets its own schema (e.g.,
school_a,school_b). All specific data (students, classes, attendances) is stored inside the tenant schema, entirely separated from others. Access is routed via subdomains (e.g.,school_a.example.com).
When making queries or performing operations programmatically, run them inside tenant context (e.g.
with tenant:) or rely on the middleware to set the schema from the request.Tenant resolution (middleware)
SmartTenantMiddleware resolves the active schema in this order:- Global paths —
/api/v1/system/,/api/schema/,/api/docs/,/api/redoc/,/admin/,/static/,/media/,/api/chatbot/stay on public (or let the app handle context). No tenant is set for system routes. - JWT — If the request has a valid Bearer JWT, the user is loaded from the public schema; if the user has a
client, that tenant’s schema is used. Ensures school users only access their own school’s data. - X-Schema-Name — Superadmins can send this header to force a schema (e.g. for support or scripting).
- Domain — If no JWT/header, the hostname is looked up in Domain (public schema); the matching Client’s schema is used.
Request flow
- Client Request: A request is dispatched to a URL (e.g.,
https://school.sms.local/api/v1/school/admissions/). - Tenant Middleware: Django intercepts the request, checks the hostname (or JWT /
X-Schema-Nameheader), looks up theDomainin the public schema, and maps it to a uniqueClienttenant. Paths like/api/v1/system/,/api/schema/,/api/docs/, and/admin/may stay on the public schema. - Schema Routing: The connection schema search path is set (e.g.
SET search_path TO tenant_schema, public). - View Processing: The request is routed to the view. Any database ORM queries run in the tenant schema.
API layout
/api/v1/system/— Platform administration (schools, platform users, roles, system auth). No tenant context./api/v1/school/— Tenant-scoped operations: auth, users, admissions, sessions, exams, marks, reports, settings, notices, RBAC, audit, promotions, etc. Nested routes undersessions/,exam-sessions/,exams/for class sessions, exam sessions, and marks./api/v1/chatbot/— Chatbot webhooks and API; runs in tenant context when applicable.
Key Subsystems
Clients Module
Handles the creation, modification, and management of Tenants (Clients) and their Domains.Core Module
The main business logic container for schools. Manages:- Academic Info: Sessions, Terms, Classes, and Forms.
- Student Data: Admissions, session registration, demographics.
- Assessment: Exam sessions, exams, marks, report cards, teacher/head/class-teacher comments.
- Settings: Session setup, promotions, general and report settings.
Chatbot Module
Integrates with the WhatsApp API.- Listens to incoming webhooks.
- Routes messages using a state machine or LLM to answer student/parent queries (e.g. results, attendance).
- Uses Celery/Redis for async processing and can generate batch report PDFs.