A Django REST Framework backend for managing recipes. Authenticated users can create recipes with tags, ingredients, and images, and browse/filter their own recipes through a REST API. The project follows the classic "recipe-app-api" tutorial architecture: a Django app served by uWSGI behind an Nginx reverse proxy, backed by PostgreSQL, and fully containerized with Docker.
- User accounts — register, obtain an auth token, and manage your own
profile (
/api/user/). - Recipes — create, read, update, and delete recipes with a title,
description, cooking time, price, an optional link, and an optional image
upload (
/api/recipe/recipes/). - Tags & ingredients — attach reusable tags and ingredients to recipes,
and filter recipes by them (
/api/recipe/tags/,/api/recipe/ingredients/). - API docs — auto-generated OpenAPI schema and Swagger UI via
drf-spectacular (
/api/schema/,/api/docs/). - Health check — a simple endpoint for readiness checks
(
/api/health-check/). - Admin site — Django admin for managing users and data (
/admin/).
All recipe/tag/ingredient endpoints require authentication (token-based) and are scoped to the logged-in user.
- Python 3.13, Django 5.2.x, Django REST Framework
- PostgreSQL 16
- drf-spectacular for OpenAPI docs
- uWSGI + Nginx for production serving
- Docker / Docker Compose for local dev and deployment
- GitHub Actions for CI (tests + flake8 lint)
app/
app/ # Django project settings, root URLs, health check
core/ # Shared models (User, Recipe, Tag, Ingredient), admin, management commands
recipe/ # Recipe/Tag/Ingredient API (serializers, views, urls)
user/ # User registration/auth API (serializers, views, urls)
proxy/ # Nginx reverse proxy config used in production
scripts/ # run.sh entrypoint (migrate + collectstatic + uwsgi)
docker-compose.yml # local development stack
docker-compose-deploy.yml # production-style stack (app + db + nginx proxy)
Dockerfile # app imageRequirements: Docker and Docker Compose.
-
Build and start the stack:
docker compose up --build
This builds the app image, starts a PostgreSQL database, waits for it to be healthy, runs migrations, and starts the Django dev server.
-
The API is available at
http://localhost:8000/.- Swagger docs:
http://localhost:8000/api/docs/ - Admin site:
http://localhost:8000/admin/ - Health check:
http://localhost:8000/api/health-check/
- Swagger docs:
-
Create an admin user (in another terminal, while the stack is running):
docker compose run --rm app sh -c "python manage.py createsuperuser"
docker compose run --rm app sh -c "python manage.py wait_for_db && python manage.py test"
docker compose run --rm app sh -c "flake8"These are the same commands run by CI on every push (see
.github/workflows/checks.yml).
docker-compose-deploy.yml runs three services: the Django app (via uWSGI),
PostgreSQL, and an Nginx proxy that serves static files and forwards
everything else to the app.
-
Copy
.env.sampleto.envand fill in real values:cp .env.sample .env
DB_NAME=dbname DB_USER=rootuser DB_PASS=changeme DJANGO_SECRET_KEY=changeme DJANGO_ALLOWED_HOSTS=127.0.0.1
Use a strong, unique
DJANGO_SECRET_KEYandDB_PASS, and setDJANGO_ALLOWED_HOSTSto your real domain(s).Create
DJANGO_SECRET_KEY:python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" -
Build and start the stack:
docker compose -f docker-compose-deploy.yml up --build -d
-
Run migrations and create a superuser as needed:
docker compose -f docker-compose-deploy.yml run --rm app sh -c "python manage.py migrate" docker compose -f docker-compose-deploy.yml run --rm app sh -c "python manage.py createsuperuser"
-
The app is served through the Nginx proxy on port
80.
| Endpoint | Description |
|---|---|
POST /api/user/create/ |
Register a new user |
POST /api/user/token/ |
Obtain an auth token |
GET/PUT/PATCH /api/user/me/ |
View/update the current user's profile |
GET/POST /api/recipe/recipes/ |
List/create recipes |
GET/PUT/PATCH/DELETE /api/recipe/recipes/{id}/ |
Retrieve/update/delete a recipe |
POST /api/recipe/recipes/{id}/upload-image/ |
Upload an image for a recipe |
GET/POST /api/recipe/tags/ |
List/create tags |
GET/POST /api/recipe/ingredients/ |
List/create ingredients |
GET /api/health-check/ |
Health check |
GET /api/docs/ |
Swagger UI |
Recipes can be filtered by tags and ingredients using comma-separated ID
lists, e.g. GET /api/recipe/recipes/?tags=1,2&ingredients=3.