Skip to main content
The Clients module manages multi-tenancy and school-level metadata. It lives in the public schema and is used by platform administrators. Each school is a Client (tenant); each Domain links a hostname to a Client so requests are routed to the correct schema.

Models (public schema)

Client (tenant)

Represents one school/organization.
  • schema_name — Database schema name (e.g. school_a). Must be unique; used by django-tenants for search_path.
  • name — Display name (e.g. “Greenwood High”).
  • code — Short unique code (e.g. school identifier).
  • setup_progress — Onboarding state: not_started, in_progress, completed.
  • is_active — If False, the tenant is disabled without deleting data.
  • created_at, updated_at — Timestamps.
auto_create_schema = True so creating a Client creates its PostgreSQL schema.

Domain

Maps a hostname to a Client.
  • domain — Hostname (e.g. school1.sms.local, app.schoola.com).
  • tenant — Foreign key to Client.
  • is_primary — Primary domain for that tenant.
Requests to an unknown domain cannot be mapped to a schema; the middleware will not set a tenant and school endpoints may 404 or fail. Ensure every host you use has a corresponding Domain pointing to a Client.

SchoolSetup

Tracks onboarding/setup progress per school.
  • client — One-to-one relationship with a Client.
  • steps — JSON list of steps (e.g. {id, title, status}).
  • contacted_by — Optional contact info.

WhatsAppContact and WhatsAppStudentMapping

  • WhatsAppContact — Maps a phone number to a Client (which school the number belongs to). Used by the chatbot to route incoming messages.
  • WhatsAppStudentMapping — Links WhatsApp contacts to students within a tenant (e.g. by admission number and student name). Used to resolve “who is this?” for results and attendance.

API (system)

Clients and domains are managed via the system API (no tenant context):
  • Schools (Clients)GET/POST/PUT/PATCH/DELETE /api/v1/system/schools/. Requires system (platform) authentication.
  • Domains are typically managed as part of or alongside Client creation (check the API schema for nested or related endpoints).
Access the system API on the public domain (e.g. main app host), not on a tenant subdomain.

Request flow

  1. Request hits a hostname (e.g. school1.sms.local).
  2. SmartTenantMiddleware looks up that hostname in Domain (public schema).
  3. The matching Client’s schema_name is set on the DB connection (search_path).
  4. All ORM queries in that request run in that tenant’s schema until the response is sent.
Integration with django-tenants is automatic: once the tenant is set, all Core and Chatbot models in that request use the tenant schema.