This commit is contained in:
2026-03-11 21:35:54 +08:00
parent 3763032a9a
commit 8a3a7e21cf
2 changed files with 135 additions and 249 deletions

View File

@@ -10,7 +10,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
```bash
# Development
python dev.py # Start dev server (Daphne ASGI + Django runserver)
python dev.py # Start dev server: Django on :8000 + Daphne WebSocket on :8001
python manage.py runserver # HTTP only (no WebSocket support)
python manage.py migrate # Apply database migrations
python manage.py makemigrations # Create new migrations
@@ -20,9 +20,10 @@ uv sync # Install dependencies from uv.lock
uv add <package> # Add a dependency
# Testing
python manage.py test # Run Django test suite
coverage run manage.py test # Run with coverage
coverage report # Show coverage report
python manage.py test # Run all tests
python manage.py test account # Run tests for a single app
python manage.py test account.tests.TestClassName # Run a single test class
coverage run manage.py test && coverage report # Run with coverage
```
## Architecture
@@ -54,36 +55,54 @@ WebSocket routing is in `oj/routing.py`.
### Settings Structure
- `oj/settings.py` — base configuration
- `oj/settings.py` — base configuration (imports dev or production settings based on `OJ_ENV`)
- `oj/dev_settings.py` — development overrides (imported when `OJ_ENV != "production"`)
- `oj/production_settings.py` — production overrides
### Base APIView
### Base APIView & View Patterns
`utils/api/api.py` provides a custom `APIView` base class used by all views. It provides:
- `self.success(data)` — returns `{"error": null, "data": data}`
- `self.error(msg)` — returns `{"error": "error", "data": msg}`
`utils/api/api.py` provides the custom base classes and decorators used by **all** views:
All views inherit from this, not Django's generic views or DRF's `APIView` directly.
- **`APIView`** — base class for all views (not DRF's `APIView`). Key methods:
- `self.success(data)` — returns `{"error": null, "data": data}`
- `self.error(msg)` — returns `{"error": "error", "data": msg}`
- `self.paginate_data(request, query_set, serializer)` — offset/limit pagination
- `self.invalid_serializer(serializer)` — standard validation error response
- **`CSRFExemptAPIView`** — same as `APIView` but CSRF-exempt
- **`@validate_serializer(SerializerClass)`** — decorator for view methods that validates `request.data` against a serializer before the method runs. On success, `request.data` is replaced with validated data.
Typical view method pattern:
```python
@validate_serializer(CreateProblemSerializer)
@super_admin_required
def post(self, request):
# request.data is already validated
return self.success(...)
```
### Authentication & Permissions
`account/decorators.py` provides decorators used on view methods:
- `@login_required`
- `@super_admin_required`
- `@check_contest_permission`
- `@login_required` / `@admin_role_required` / `@super_admin_required`
- `@problem_permission_required`
- `@check_contest_permission(check_type)` — validates contest access, sets `self.contest`
- `ensure_created_by(obj, user)` — helper that raises `APIError` if user doesn't own the object
### Judge System
- `judge/dispatcher.py` — dispatches submissions to the judge sandbox
- `judge/dispatcher.py` — dispatches submissions to the judge sandbox (JudgeServer)
- `judge/tasks.py` — Dramatiq async tasks for judging
- `judge/languages.py` — language configurations (compile/run commands, limits)
Judge status codes are defined in `utils/constants.py` and must match the frontend's `utils/constants.ts`.
Judge status codes are defined in `submission/models.py` (`JudgeStatus` class, codes -2 to 8) and must match the frontend's `utils/constants.ts`.
### Site Configuration (SysOptions)
`options/options.py` provides `SysOptions` — a metaclass-based system for site-wide configuration stored in the database with thread-local caching. Access settings like `SysOptions.smtp_config`, `SysOptions.languages`, etc.
### WebSocket (Channels)
`submission/consumers.py` — WebSocket consumer for real-time submission status updates. Uses `channels-redis` as the channel layer backend.
`submission/consumers.py` — WebSocket consumer for real-time submission status updates. Uses `channels-redis` as the channel layer backend. Push updates via `utils/websocket.py:push_submission_update()`.
### Caching
@@ -95,14 +114,14 @@ Redis-backed via `django-redis`. Cache keys use MD5 hashing for consistency. See
### Data Directory
Test cases and submission outputs are stored in a separate data directory (configured in settings, not in the repo). The `data/` directory in the repo contains configuration templates.
Test cases and submission outputs are stored in a separate data directory (configured in settings, not in the repo). The `data/` directory in the repo contains configuration templates and `secret.key`.
## Key Domain Concepts
| Concept | Details |
|---|---|
| Problem types | ACM (binary accept/reject) vs OI (partial scoring) |
| Judge statuses | Numeric codes -2 to 9 (defined in `utils/constants.py`) |
| Judge statuses | COMPILE_ERROR(-2), WRONG_ANSWER(-1), ACCEPTED(0), CPU_TLE(1), REAL_TLE(2), MLE(3), RE(4), SE(5), PENDING(6), JUDGING(7), PARTIALLY_ACCEPTED(8) |
| User roles | Regular / Admin / Super Admin |
| Contest types | Public vs Password Protected |
| Supported languages | C, C++, Python2, Python3, Java, JavaScript, Golang, Flowchart |