Backend Architecture Overview¶
Author: Zhenyu Yang yangzhenyu@sust.edu.cn
Last updated: Apr 24, 2026
This document describes the shared structure and cross-module constraints of the Django backend. For specific business rules, see the corresponding app pages.
Directory Structure¶
backend/
├── apps/
│ ├── accounts/
│ ├── classrooms/
│ ├── courses/
│ ├── signage/
│ ├── checkins/
│ ├── borrowings/
│ ├── repairs/
│ ├── abuse/
│ └── logs/
├── classroom_manager/
│ ├── settings/
│ └── urls.py
├── common/
├── services/
└── manage.py
Configuration & Runtime¶
The default settings module is
classroom_manager.settings.base;manage.py,wsgi.py, andasgi.pyall point directly to it.The database defaults to MySQL; connection parameters come from
MYSQL_*environment variables.The default language is
zh-hans; the default timezone isAsia/Shanghai.REST Framework requires authentication by default; the default pagination class is
common.pagination.DefaultPaginationwith a max page size of 200.Login throttling uses
LOGIN_THROTTLE_RATE, defaulting to5/minute.The upload directory defaults to
LOCAL_UPLOAD_DIR=/data/uploads; the access prefix defaults to/media/uploads/.
Global Routing¶
Django admin entry:
/django-admin/Business API common prefix:
/api/v1/The root URL configuration is defined in
backend/classroom_manager/urls.py.Routes are organized in two ways:
DRF
router.register(...)manages standard resources such asusers,classrooms,borrow, andcourses.path(...)manages standalone actions such as authentication, uploads, system config, and signage activation.
Authentication Model¶
Default authentication classes:
apps.accounts.authentication.CookieJWTAuthenticationrest_framework.authentication.SessionAuthentication
After successful email or WebAuthn login on the web, tokens are returned and
token,refresh_token,logged_in, andcsrftokencookies are set.The WeChat mini program login does not use cookies; it returns access/refresh tokens in the response body.
CookieJWTAuthenticationreads theAuthorizationheader first, then falls back to thetokencookie.The user’s active role
current_roleis not persisted; it comes from the JWT claim or theX-Current-Rolerequest header. Middleware validates that it exists inuser.roles.Signage devices do not use user JWTs; they use
apps.signage.authentication.SignageDeviceAuthenticationwith the header formatAuthorization: Bearer <device_token>.
Cross-Module Dependencies¶
coursesprovides the source of truth for classroom schedules;classrooms,signage,borrowings, andcheckinsall depend onCourseOccurrence.borrowingsconflict detection checks both manual reservations and course occupancy.checkinsanchorsCheckinSessioncreation toCourseOccurrence.common.SystemConfigprovides seasonal schedules and semester start dates tocourses.logsis reused across business modules viaOperationLogContextMiddlewareandlog_operation().
Responses & Pagination¶
Two response styles coexist in the project:
The
{code, message, data}wrapper fromcommon.responses.success/errorDRF’s default pagination or serializer responses
Most custom actions use the unified wrapper.
Endpoints that rely on the default
ModelViewSet.list/retrieve/updateimplementation may return DRF’s native structure.During frontend-backend integration, do not assume all endpoints uniformly return
{code, message, data}.
Current Implementation Caveats¶
The log permission class
apps.logs.permissions.IsLogAdminstill reads the legacyuser.rolefield, so non-Djangois_superuser/is_staffaccounts typically cannot reliably access log endpoints.services/file_storage.pyalready has a local/S3 dual-backend abstraction, butcommon.views.upload_filestill writes directly to the local filesystem.Signage already has independent device authentication, but it is currently used only for information display and is not integrated into the check-in write flow.