- Environment-split settings: base/local/test/prod with django-environ - Postgres + Redis + Celery wiring (broker, beat, result backend) - All 9 domain app stubs: accounts, courses, cms, tracking, quizzes, training, certificates, reports, notifications - api app: /healthz/ endpoint, custom DRF exception handler, SecurityAuditMiddleware, permissions/throttle/upload-validation stubs - DRF global baseline: JWT+session auth, closed-by-default permissions, cursor/page pagination, drf-spectacular schema generation - Dockerfile (multi-env build arg), docker-compose.yml (local), docker-compose.test.yml (CI-friendly tmpfs Postgres) - pytest.ini with smoke + settings marker definitions - tests/test_smoke.py: startup, URL resolution, healthcheck shape - tests/test_settings_matrix.py: per-profile security assertions - .github/workflows/ci.yml: test, lint, schema CI jobs - .env.example with all required vars documented - .gitignore Co-Authored-By: Paperclip <noreply@paperclip.ing>
29 lines
801 B
Python
29 lines
801 B
Python
import uuid
|
|
from rest_framework.views import exception_handler
|
|
from rest_framework.response import Response
|
|
|
|
|
|
def custom_exception_handler(exc, context):
|
|
response = exception_handler(exc, context)
|
|
if response is None:
|
|
return None
|
|
|
|
request = context.get("request")
|
|
request_id = (
|
|
getattr(request, "META", {}).get("HTTP_X_REQUEST_ID") or str(uuid.uuid4())
|
|
)
|
|
|
|
code = getattr(exc, "default_code", "error")
|
|
message = str(exc.detail) if hasattr(exc, "detail") else str(exc)
|
|
details = exc.detail if isinstance(getattr(exc, "detail", None), dict) else {}
|
|
|
|
response.data = {
|
|
"error": {
|
|
"code": code,
|
|
"message": message,
|
|
"details": details,
|
|
"request_id": request_id,
|
|
}
|
|
}
|
|
return response
|