Minimal, API-first hospital management backend built with Django + Django REST Framework. Designed for modular growth, clear separation of concerns, and predictable production scaling.
- Key tables:
users(UUID PK),patients,doctors,appointments,available_times,reviews,qualifications. - Relationships: normalized one-to-many and many-to-many where appropriate (doctor β specializations, doctor β qualifications, patient β appointments).
- Scalability choices: UUID primary keys for horizontal safety, targeted indexes on
email,user_id, andappointment_time, and normalized schema to avoid redundancy. - Media & files: media stored via configured
MEDIA_ROOTwith adapters for S3/R2 in production; media references kept in a dedicated table/field to simplify migration.
Routing follows /v1/api/ base path and modular Django apps (users, patient, doctor, appointment, public_portal, operations). Each app exposes viewsets/serializers and dedicated routers; versioning is applied at the URL level for safe evolution.
Implemented features
- Authentication: registration, OTP activation, JWT (access/refresh), token verify/refresh, password reset (OTP).
- Patient management: profile, list, self profile (
patients/me/). - Doctor management: public listing, profile management, qualifications, available times.
- Scheduling: appointment creation and status workflow (patient & doctor views).
- Reviews & feedback: doctor reviews, public contact / bug reports.
- Public portal: public doctor list, services, public reviews.
- API docs: OpenAPI schema + Swagger UI.
Scalability / separation of concerns
- Containerized:
docker composedevelopment, discretebackendservice. - Modular apps: swap DB, add caching, and resume background workers independently (Postgres / Redis / Celery path ready).
- Flow (minimal):
Register β OTP activation β JWT login (access/refresh) β token refresh / verify β password reset (OTP). - Typical endpoints:
/v1/api/user/register/,/v1/api/user/account/activate/,/v1/api/user/login/,/v1/api/user/token/refresh/,/v1/api/user/token/verify/,/v1/api/user/forget-password/(OTP flows follow same pattern).
Examples (curl)
Register + activate OTP (example):
# 1) Register (returns pending verification)
curl -s -X POST /v1/api/user/register/ \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"Pass1234"}'
# 2) Activate (OTP delivered via email/SMS)
curl -s -X POST /v1/api/user/account/activate/ \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","otp":"123456"}'Login + token refresh:
# 1) Login -> returns {"access":"<jwt>","refresh":"<refresh_token>"}
curl -s -X POST /v1/api/user/login/ \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"Pass1234"}'
# 2) Refresh access token
curl -s -X POST /v1/api/user/token/refresh/ \
-H "Content-Type: application/json" \
-d '{"refresh":"<refresh_token>"}'| Method | Path | Purpose | Auth |
|---|---|---|---|
| POST | /v1/api/user/register/ | Register new user | No |
| POST | /v1/api/user/account/activate/ | Activate account (OTP) | No |
| POST | /v1/api/user/account/activate/otp/resend/ | Resend activation OTP | No |
| POST | /v1/api/user/login/ | Login (may require OTP verify) | No |
| POST | /v1/api/user/login/otp/resend/ | Resend login OTP | No |
| POST | /v1/api/user/login/otp/verify/ | Verify login OTP | No |
| POST | /v1/api/user/token/refresh/ | Refresh JWT access | No (uses refresh token) |
| POST | /v1/api/user/token/verify/ | Verify token validity | No |
| POST | /v1/api/user/change-password/ | Change password (auth) | Yes |
| POST | /v1/api/user/forget-password/ | Request password reset (OTP) | No |
| POST | /v1/api/user/forget-password/otp/send/ | Send password reset OTP | No |
| POST | /v1/api/user/forget-password/otp/resend/ | Resend password OTP | No |
| POST | /v1/api/user/forget-password/confirm/ | Confirm password reset | No |
| GET | /v1/api/user/list/ | List users (admin) | Yes |
| Method | Path | Purpose | Auth |
|---|---|---|---|
| GET | /v1/api/patient/patients/ | List patients | Yes |
| GET | /v1/api/patient/patients/{user__email}/ | Patient by email | Yes |
| GET | /v1/api/patient/patients/me/ | My patient profile | Yes |
| PUT/PATCH/DELETE | /v1/api/patient/patients/me/ | Update / delete own profile | Yes |
| Method | Path | Purpose | Auth |
|---|---|---|---|
| GET | /v1/api/doctor/list/ | Public doctor list | No |
| GET | /v1/api/doctor/profile/{user__email} | Doctor profile by email | No |
| GET | /v1/api/doctor/profile/me/ | My doctor profile | Yes |
| PUT/PATCH/DELETE | /v1/api/doctor/profile/me/ | Manage own profile | Yes |
| Method | Path | Purpose | Auth |
|---|---|---|---|
| GET/POST | /v1/api/appointment/doctor/ | Doctor-side appointments list/create | Yes |
| PATCH | /v1/api/appointment/doctor/{id}/update_status/ | Update appointment status | Yes |
| GET/POST | /v1/api/appointment/patient/ | Patient-side appointments list/create | Yes |
| Method | Path | Purpose | Auth |
|---|---|---|---|
| POST | /v1/api/public-portal/contact-us/ | Submit contact form | No |
| POST | /v1/api/public-portal/report-bug/ | Submit bug report | No |
| GET | /v1/api/public-portal/list/doctor/ | Public doctor list | No |
| GET | /v1/api/public-portal/list/doctor/reviews/ | Public doctor reviews | No |
| GET | /v1/api/public-portal/services/ | Public services list | No |
| Method | Path | Purpose | Auth |
|---|---|---|---|
| GET/POST | /v1/api/doctor/available-times/ | Manage doctor available times (admin/doctor) | Yes |
| GET/POST | /v1/api/doctor/available-times-patient/ | Patient view / request available times | Yes |
| GET/PUT/PATCH/DELETE | /v1/api/doctor/available-times/{id}/ | Available time detail | Yes |
| GET/POST | /v1/api/doctor/designations/ | Doctor designations (CRUD) | Yes |
| GET/POST | /v1/api/doctor/specializations/ | Specializations (CRUD) | Yes |
| Method | Path | Purpose | Auth |
|---|---|---|---|
| GET/POST | /v1/api/doctor/reviews/ | List / submit reviews | GET: No / POST: Yes |
| GET/PUT/PATCH/DELETE | /v1/api/doctor/reviews/{id}/ | Review detail / manage | Yes |
| Method | Path | Purpose | Auth |
|---|---|---|---|
| GET | /v1/api/doctor/{doctor_id}/qualifications/ | List doctor qualifications | Yes |
| POST | /v1/api/doctor/qualifications/apply/ | Apply qualification | Yes |
| POST | /v1/api/operations/apply/to-be/doctor/ | Apply to become doctor | Yes |
git clone <repo>&&cd repo- copy
.env.exampleβ.envand set vars. docker compose up --builddocker compose exec backend python manage.py migratedocker compose exec backend python manage.py createsuperuserdocker compose exec backend python manage.py test
.env.example
SECRET_KEY=replace_me
DATABASE_URL=sqlite:///db.sqlite3
DEBUG=True
MEDIA_ROOT=/data/media
EMAIL_HOST=smtp.example.com
EMAIL_PORT=587
EMAIL_HOST_USER=you@example.com
EMAIL_HOST_PASSWORD=secret
JWT_ACCESS_LIFETIME=5m
JWT_REFRESH_LIFETIME=7dRecommended production stack: Postgres, S3 / R2 for media, Redis (cache + broker), Celery (background tasks), Gunicorn + Nginx as reverse proxy. For cloud migration: start with Docker Compose for CI/CD, then extract services into Kubernetes manifests (Deployment + Service + Ingress). Convert volume mounts to object storage and attach Redis/Celery as managed services in K8s.
- Move primary DB to PostgreSQL and enable partitioning/index review.
- Add Redis caching for hot reads (doctor lists, availability).
- Introduce Celery for async email, reports, and heavy exports.
- Optional: migrate media to S3/R2 and ensure signed URLs for secure media delivery.
- File issues for feature requests or bugs; reference minimal repro steps.
- Open PRs against
developwith tests and linting; include changelog entry. - CI enforces tests + linters; maintainers will review and merge.
(See repository CODE_OF_CONDUCT placeholder file.)
Licensed under an open-source license (add LICENSE file). Maintainer: Maintainer Name β contact via repo issues or maintainer email in .env.



