Django backend for OpenCap.
The API serves both the webapp and the iOS app. It stores sessions, subjects, trials, and videos, and queues recordings for the processing pipeline. Background work (archive builds, session downloads, scheduled cleanup) runs in Celery workers backed by Redis, not in the web process.
- User enters the website (app.opencap.ai)
- The website calls the backend and creates a session
- The session generates a QR code displayed in the webapp
- User scans the code with the iOS app. App uses the code to connect directly to the backend
- User clicks record in the webapp -> this invokes backend to change session state to recording
- iPhones pull session state every 1sec and see it's in 'recording' state. They start recording
- User clicks stop recording changing state to 'upload'
- iPhones upload the videos
- When all videos are uploaded, backend changes the state to processing and adds videos to the queue for processing
- Video processing pipeline pools sessions in 'processing' state and processes them
- After processing, results are sent to the backend and the backend changes its state to 'done'
Beyond requirements.txt, which covers pip packages only:
- Python 3.7 — the pinned dependencies do not install on newer versions
- PostgreSQL —
mcserver/settings.pyalways uses thepostgresqlbackend
Depending on the work:
- Redis — to run Celery. The API serves requests without it, but asynchronous work (session downloads, cleanup jobs) never runs
- gettext — to compile translations
git clone https://github.com/opencap-org/opencap-api.git
cd opencap-api
conda create -n opencap python=3.7
conda activate opencap
pip install -r requirements.txtCreate a .env file in the repository root. The required variables are the config(...) calls in mcserver/settings.py that have no default; ask a maintainer for development values.
python manage.py migrate
python manage.py runserverThe API is served at http://localhost:8000/.
Asynchronous work needs Celery processes running alongside the server:
celery -A mcserver worker -l info # session downloads, archive builds
celery -A mcserver beat -l info # scheduled jobsWith the server running:
- Swagger UI:
http://localhost:8000/docs/ - ReDoc:
http://localhost:8000/redocs/
Routes are registered in mcserver/urls.py. Most come from the viewsets in mcserver/views.py, which also add a number of custom actions on top of the standard REST routes. Requests authenticate with a DRF token, or a session cookie for the browsable API.
- Add the field to the model in
mcserver/models.py - Run
python manage.py makemigrations - Run
python manage.py migrate— careful, this modifies the database - Add the field to
mcserver/serializers.pyif the API should expose it - Update
mcserver/admin.pyif it should appear in the admin
Tests need a valid .env and a database they are allowed to create.
python manage.py test tests # whole suite
python manage.py test tests.test_permissions # one moduleNote: Some tests may be outdated and fail. Test
test_permissions.SessionsPermissionsTestsmay fail on Windows but works on Ubuntu and macOS.
See the Django translation docs. This requires gettext — restart your terminal or IDE after installing it.
From the mcserver folder:
django-admin makemessages -l es # create or refresh files for a language
django-admin compilemessages # compile themDeployment is automated with GitHub Actions. Each push builds Dockerfile, pushes the image to ECR, and forces a new ECS deployment.
| Branch | Workflow | Effect |
|---|---|---|
dev |
.github/workflows/ecr-dev.yml |
Builds opencap/api-dev; redeploys api-server-dev, api-server-celery-dev, api-server-celery-beat-dev in opencap-api-cluster-dev |
main |
.github/workflows/ecr.yml |
Builds opencap/api; redeploys api-server, api-server-celery, api-server-celery-beat in opencap-api-cluster |
Two things are not automated:
- Migrations. If your change adds one, run
python manage.py migrateagainst that environment's database after the deploy. - Environment variables. New settings have to be added to the ECS task definitions; they are not read from this repository.
- Open an issue describing the change first
- Branch off
dev - Open a pull request against
dev, referencing the issue
dev is the integration branch. Changes reach production through a dev → main pull request. Since a push to main deploys production immediately, work should not target it directly.
Apache License 2.0 — see LICENSE.md for details.