Django 6 + DRF API for AlienCommons. Python 3.14, ASGI via Daphne/Channels. Depends on the workspace package drf-std-response (see packages/drf-std-response/AGENTS.md).
backend/— Django project:settings/,urls.py,asgi.py,wsgi.py.backend/settings/—base.py(prod-like foundation) +dev.py,stg.py,pro.py,test.pyoverlays.core/— shared code: response/pagination/viewset mixins, validators, middleware, model mixins, fields, signals, test helpers.- The other top-level Python packages are Django apps (see table below). Each app typically has
models.py,serializers.py,services.py,views.py,permissions.py,admin.py,migrations/, and atests/package. manage.py— entrypoint; defaultDJANGO_SETTINGS_MODULEisbackend.settings.dev.
| App | Domain |
|---|---|
users |
Users, sessions, email verification, subscriptions |
articles |
Articles, published articles, collections, article workflow |
bookmarks |
Bookmark folders and article bookmarks |
comments |
Article comments and replies |
notifications |
Notification events, fan-out deliveries, inbox APIs |
posts |
Community posts and related content |
reactions |
Like/dislike targets and user reactions |
reports |
Content and user moderation reports |
tasks |
Scheduled/background task definitions |
core |
Shared utilities, responses, permissions, test helpers |
logs |
(Referenced by ruff/lint scope; treat as app-shaped module) |
The ruff lint scope in CI is exactly:
articles bookmarks comments backend core logs notifications posts reactions reports tasks users manage.py. When you add a new app, add it here, in.github/workflows/ci.yml(backend-lintstep), and in any app-list settings (e.g.INSTALLED_APPS, router registries).
- PostgreSQL 18 — primary data store.
- Redis 8 — django-redis cache, Django sessions, RQ broker.
- RQ workers via
django-tasks-rq— queuesdefault,email,maintenance(seemake dev-backend-runrqworker). - Scheduler —
make dev-backend-runscheduler→python manage.py runscheduler. - AlienMark — internal Fastify Markdown rendering service (
apps/alienmark/); backend calls it over HTTP. - Media storage — local filesystem in
dev/test; S3-compatible viadjango-storagesinstg/prowhen configured. Static files are deploy artifacts; media files are user/runtime data — they have different lifecycles.
Run inside apps/backend/ unless noted. The Compose equivalents run inside the backend-api container.
| Action | Local | Compose |
|---|---|---|
| Tests | uv run python manage.py test (or --settings=backend.settings.test) |
make dev-backend-test |
| System check | uv run python manage.py check |
make dev-backend-check |
| Lint | uv run ruff check articles bookmarks comments backend core logs notifications posts reactions reports tasks users manage.py |
(run locally) |
| Make migrations | uv run python manage.py makemigrations |
make dev-backend-makemigrations |
| Apply migrations | uv run python manage.py migrate |
make dev-backend-migrate |
| Shell | uv run python manage.py shell |
make dev-backend-shell |
| Create superuser | uv run python manage.py createsuperuser |
make dev-backend-createsuperuser |
| Init scheduled tasks | uv run python manage.py init_tasks |
make dev-backend-init-tasks |
| Run scheduler | uv run python manage.py runscheduler |
make dev-backend-runscheduler |
| Run RQ worker | uv run python manage.py rqworker default email maintenance |
make dev-backend-runrqworker |
| Bash in container | — | make dev-backend-bash |
backend.settings.base— shared production-like foundation. Layer environment-specific behavior on top of it, not by editing base.backend.settings.dev/stg/pro— deployment overlays.backend.settings.test— intentionally independent. Must stay fast, deterministic, and isolated from PostgreSQL, Redis, S3, and external services unless a test explicitly opts into an integration path. Don't add network/IO dependencies totestcasually.ruff.tomlallowsF403/F405only insidebackend/settings/{dev,pro,stg}.py(star-import settings files).- Keep secrets/AWS credentials out of settings. EC2/ECS IAM roles should provide AWS creds in hosted environments — do not add static AWS keys.
- Service layer is authoritative for workflow logic. When an app has a
services.py(orservices/), put business/workflow logic there — not in views or serializers. Views orchestrate; services decide. - Use the standard response envelope. API responses go through the project-standard envelope (
success,message,code,data,errors,meta) provided bydrf-std-response. Don't return ad-hoc DRFResponseshapes from API views. See the DRF envelope guide forEnvelopeMixin,ServiceError, and the exception handler. - Permissions are explicit. Use DRF permission classes; don't gate writes inside view bodies.
- Cross-cutting surfaces are conservative edits: authentication, permissions, sessions, email verification, article workflow state machines, scheduler, and storage. Read the surrounding code before changing them.
- Add a focused migration whenever models change. One logical change per migration.
- Never edit an applied migration unless deliberately rewriting history.
- Don't squash or rename migrations casually — downstream deployments and CI depend on the linear history.
- Tests live in each app's
tests/package, next to the code they cover. - Default test runner: Django's built-in runner (
manage.py test) underbackend.settings.test. - Add or update tests whenever behavior, permissions, workflow transitions, task scheduling, storage, or API contracts change — even if not explicitly requested.
- Keep tests hermetic: use fixtures/factories, don't depend on
dev/stgdata or external HTTP.
- Responses wrapped in the standard envelope via
EnvelopeMixin/format_success_response. - Errors normalized through the
drf_std_responseexception handler. RaiseServiceError(detail=..., code=...)from service code for client-facing errors. - Preserve existing URL naming and DRF router conventions unless the change is an intentional API version bump.
- Serializer validation errors must stay compatible with the custom exception handler (don't bypass DRF validation).
Run the smallest relevant check. If a check can't run, say so in the final response.
# Tests (matches CI backend-tests job)
uv run python manage.py test
# Lint (matches CI backend-lint job scope exactly)
uv run ruff check articles bookmarks comments backend core logs notifications posts reactions reports tasks users manage.py
# System check
uv run python manage.py checkAfter any backend change, inspect .github/workflows/ci.yml and decide whether the backend-lint or backend-tests jobs (or deployment/docs workflows) need updates — e.g. when adding/removing apps, changing settings modules, build commands, or verification steps.