Back to all posts

Add a Django REST Framework API to the Tic Tac Toe Game

Define the API work, review the generated Django files, and verify separate API and PostgreSQL health endpoints.

Watch the video

In this lesson I direct GPT-6 Astra in Codex CLI to add a Django REST Framework API to our tic tac toe project. I work in VS Code with NVDA, although screen-reader audio is muted in this recording. The deliverable is a running API with two health checks. Player records and saved games are still future work.

Before you start

Use the tic tac toe repository, with Docker Desktop running. The earlier run the game lesson covers getting it onto your computer, and the PostgreSQL lesson explains the database service. The current repository already includes this API, so you can inspect and run it without asking an AI to recreate it.

Define what completion means

Before implementation, I give the coding tool a plan file and a concrete definition of done: Django REST Framework in its own container, one route that reports API health, and another route that makes a real request to PostgreSQL. I also ask it to account for Compose networking. The frontend will not store games in this step.

For your own changes, write down the files and behavior you expect, then review the proposed changes against that list. A completion message is a starting point for verification. In the recording, I copy the response into a new editor so I can read it alongside the generated files.

Review the generated project

The back-end folder contains the Dockerfile, manage.py, pyproject.toml and the gaming_center Django project. I inspect the dependency list for Django, Django REST Framework and psycopg, then read settings.py, urls.py and health.py. Use the checked-in dependency files and lockfile for the version you downloaded, rather than installing versions from the narration.

The API health view returns an OK response. The database view executes a small database query and handles a database failure separately. The Django REST Framework view documentation explains the function-based API view pattern used here.

Understand the container addresses

For the current repository, the browser connects to the app on localhost:5173. Vite forwards /api/ requests to api:8000 inside Compose, and Django connects to database:5432. Inside a container, localhost means that container itself. Compose service names identify the other services on the network. See Docker's Compose networking guide.

Run the current implementation

From the repository root, start the services and read their status:

docker compose up -d
docker compose ps

Wait for app, api and database to become healthy. The current README documents the setup. This is a local development stack, with development credentials and servers; it is not an internet deployment recipe.

Verify both routes

Open each address in your browser, keeping the trailing slash:

http://localhost:5173/api/health/
http://localhost:5173/api/health/database/

Both healthy responses contain {"status":"ok"}. The first establishes that the API is responding; the second checks a query to PostgreSQL. The current implementation returns HTTP 503 with an unavailable status for a database failure. A passing API-only check does not establish database health.

As an additional check documented in the current project, run the Django checks and tests:

docker compose exec api uv run --locked python manage.py check
docker compose exec api uv run --locked python manage.py test

If a service fails, inspect its logs with docker compose logs --tail=100 api or the corresponding database service name. Keep the actual error and test result in your notes. These commands are follow-along instructions; this article does not claim a fresh test run on your computer.

Stop and record the next step

Run docker compose down from the project root when finished. Record what was implemented, what you verified and what remains. The next feature work is game models and routes, followed by connecting the frontend. The accessibility review video examines the game's interface and the limits of AI-assisted testing.