In this tutorial, we’ll build a simple Todo API using Django REST Framework with full CRUD functionality.
- Install Django + DRF
pip install django djangorestframeworkExplanation
- Django → Web framework (handles backend, database, logic)
- Django REST Framework (DRF) → Converts Django into an API builder
DRF helps you return data in JSON format
2. Create project + app
django-admin startproject todo_project
cd todo_projectpython manage.py startapp todosExplanation
project→ Main configuration (settings, URLs)app→ Where your actual feature lives (Todo logic)
Think:
- Project = container
- App = feature/module
3. Add apps in settings.py
INSTALLED_APPS = [
...
'rest_framework',
'todos',
]Explanation
'rest_framework'→ enables DRF features'todos'→ tells Django to use your app
If you don’t add this, Django won’t recognize your app
4. Create Todo Model (todos/models.py)
from django.db import models
class Todo(models.Model):
title = models.CharField(max_length=255)
completed = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.titleExplanation
__str__ defines how the object is displayed as a string
In simple terms:
“What should Django show when this object is printed or viewed?”
🔍 Without __str__
If you don’t define it, Django shows something like:
Todo object (1)Explanation
This defines your database table
title→ task namecompleted→ true/false statuscreated_at→ auto timestamp
Django converts this into a SQL table
5. Migrate database
python manage.py makemigrations
python manage.py migrateExplanation
makemigrations→ creates migration filemigrate→ applies changes to database
Without this, your model won’t exist in DB
6. Create Serializer (todos/serializers.py
from rest_framework import serializers
from .models import Todoclass TodoSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = '__all__'Explanation
Serializer = converter
Converts:
- Python object → JSON (response)
- JSON → Python object (request)
Example:
{
"title": "Learn DRF",
"completed": false
}7. Create Views (CRUD APIs)
Get Shoomankhatri’s stories in your inbox
Join Medium for free to get updates from this writer.
todos/views.py
from rest_framework import generics
from .models import Todo
from .serializers import TodoSerializer# GET all + POST create
class TodoListCreateView(generics.ListCreateAPIView):
queryset = Todo.objects.all().order_by('-created_at')
serializer_class = TodoSerializer
# GET single + PUT + DELETE
class TodoDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Todo.objects.all()
serializer_class = TodoSerializer
Explanation
ListCreateAPIView
Handles:
GET /todos/→ get all todosPOST /todos/→ create new todo
RetrieveUpdateDestroyAPIView
Handles:
GET /todos/1/→ get one todoPUT /todos/1/→ updateDELETE /todos/1/→ delete
What is Generics
Generics (in Django REST Framework) are pre-built views that automatically handle common API operations like GET, POST, PUT, and DELETE, so you don’t have to write the logic yourself.
Why use generics?
DRF gives ready-made logic
Instead of writing everything manually:
- Less code
- Faster development
8. Create URLs (todos/urls.py)
from django.urls import path
from .views import TodoListCreateView, TodoDetailViewurlpatterns = [
path('todos/', TodoListCreateView.as_view(), name='todo-list-create'),
path('todos/<int:pk>/', TodoDetailView.as_view(), name='todo-detail'),
]Explanation
This connects:
- URL → View
Example:
/todos/→ list & create/todos/1/→ single item
9. Connect main URLs (todo_project/urls.py)
from django.contrib import admin
from django.urls import path, includeurlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('todos.urls')),
] ,Explanation
/api/todos/→ your API endpointinclude()→ connects app URLs to project
10. Testing Your API
Create Todo
POST /api/todos/Body:
{
"title": "Learn Django",
"completed": false
}Get All Todos
GET /api/todos/Get One Todo
GET /api/todos/1/Update Todo
PUT /api/todos/1/Delete Todo
DELETE /api/todos/1/Final Understanding
This app follows a clean flow:
Model → Serializer → View → URL → APIData flow:
- User sends request
- View handles it
- Serializer converts data
- Model interacts with DB
- Response returned as JSON
Summary
- Django handles backend logic
- DRF makes API building easy
- Generics reduce code
- Serializer handles JSON conversion








