This project is a practical and educational example of how to build a professional REST API with:
- Django 4.2 + Django REST Framework
- SOLID principles and Clean Code
- Docker and docker-compose
- Makefile to automate tasks
- Unit and functional tests with Pytest
Show how to structure a Django project in a modular, maintainable, and easily testable way by separating responsibilities into layers.
| Layer | Folder | Responsibility |
|---|---|---|
| API / Infrastructure | api/ |
Global Django configuration and URLs |
| Domain / Application | tasks/ |
Models, business logic, serialization, services, and endpoints |
| External infrastructure | Dockerfile, docker-compose.yml |
Containers and dependencies |
| Automation / DevOps | Makefile |
Commands for common tasks |
http://0.0.0.0:8000/api/tasks/
http://0.0.0.0:8000/admin/tasks/task/
django-api-rest-example/
├── Makefile
├── Dockerfile
├── README.md
├── docker-compose.yml
├── entrypoint.sh
├── requirements.txt
├── pytest.ini
├── manager.py
├── api/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── tasks/
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── serializers.py
├── repositories.py
├── services.py
├── views.py
├── urls.py
└── tests/
├── test_serializers.py
├── test_services.py
└── test_api.py
└── migrations/
├── __init__.py
├── 0001_initial.py
git clone git@github.com:jcmoro/api-rest-django-example.gitmake upmake migrateThe API will be available at 👉 http://localhost:8000/api/tasks/
Run all tests (unit + functional):
make testRun only unit tests:
make test-unitRun only functional tests:
make test-functional- Single Responsibility Principle (SRP): each class has a specific purpose.
- Open/Closed Principle (OCP): services and repositories can be extended without modifying existing code.
- Dependency Inversion Principle (DIP): services depend on abstractions (repositories), not concrete implementations.
- Clean Code: readable code, short functions, descriptive names, and clear separation of concerns.
| Method | Path | Description |
|---|---|---|
GET |
/api/tasks/ |
List tasks |
POST |
/api/tasks/ |
Create a new task |
POST |
/api/tasks/{id}/complete/ |
Mark a task as completed |
GET |
/api/tasks/{id}/ |
Task detail |
PUT/PATCH/DELETE |
/api/tasks/{id}/ |
CRUD operations |
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
[
{
"id": 1,
"title": "Sample task 1",
"description": "Sample task 1 description",
"completed": false,
"owner": 1,
"created_at": "2025-10-26T18:31:31.452551Z"
}
]
To see all available options in the Makefile, run:
make helpUsage:
make <target>
📖 Automatic help
help Display help
create-admin Create user admin django
🐳 Docker
build Build Docker images (no cache)
up Start containers (build first)
run Start the development server
down Stop and remove containers, networks and volumes
restart Fully restart the environment
logs Show web service logs
⚙️ Django
migrate Run Django migrations
makemigrations Create new migrations
shell Open an interactive Django shell
🧪 Tests
test Run all tests (unit + functional)
test-unit Run only mocked unit tests (fast, no DB)
test-functional Run functional tests (require DB)
list-tasks List tasks locally
🔍 Code quality
lint Run flake8 to check style
format Run black to auto-format code
José Carlos Moro Díaz
💼 GitHub: @jcmoro
✉️ Contact: jcmorodiaz@gmail.com

