CRUD stands for Create, Read, Update, and Delete. These are the four fundamental operations performed on data in most applications.
In Django REST Framework (DRF), CRUD operations are typically implemented using APIView, serializers, and Django models.
In this tutorial, we’ll build a complete Employee API that supports all CRUD operations.
Creating the Model
First, create an Employee model.
from django.db import models
class Employee(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
department = models.CharField(max_length=100)
def __str__(self):
return self.name
Run migrations:
python manage.py makemigrations
python manage.py migrate
Creating the Serializer
Create serializers.py:
from rest_framework import serializers
from .models import Employee
class EmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
fields = "__all__"
The serializer will handle data conversion and validation.
Create Operation (POST)
The Create operation adds a new record to the database.
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Employee
from .serializers import EmployeeSerializer
class EmployeeCreateAPIView(APIView):
def post(self, request):
serializer = EmployeeSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(
serializer.data,
status=status.HTTP_201_CREATED
)
return Response(
serializer.errors,
status=status.HTTP_400_BAD_REQUEST
)
Request:
{
"name": "Tarun Kumar",
"email": "tarun@example.com",
"department": "IT"
}
Response:
{
"id": 1,
"name": "Tarun Kumar",
"email": "tarun@example.com",
"department": "IT"
}
Read Operation (GET)
Read operations retrieve data from the database.
Retrieve All Records
class EmployeeListAPIView(APIView):
def get(self, request):
employees = Employee.objects.all()
serializer = EmployeeSerializer(
employees,
many=True
)
return Response(serializer.data)
Response:
[
{
"id": 1,
"name": "Tarun Kumar",
"email": "tarun@example.com",
"department": "IT"
}
]
Retrieve Single Record
class EmployeeDetailAPIView(APIView):
def get(self, request, pk):
employee = Employee.objects.get(pk=pk)
serializer = EmployeeSerializer(employee)
return Response(serializer.data)
Request:
GET /api/employees/1/
Response:
{
"id": 1,
"name": "Tarun Kumar",
"email": "tarun@example.com",
"department": "IT"
}
Update Operation (PUT)
The PUT method updates an entire record.
class EmployeeUpdateAPIView(APIView):
def put(self, request, pk):
employee = Employee.objects.get(pk=pk)
serializer = EmployeeSerializer(
employee,
data=request.data
)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors)
Request:
{
"name": "Tarun Kumar",
"email": "tarun@example.com",
"department": "HR"
}
Response:
{
"id": 1,
"name": "Tarun Kumar",
"email": "tarun@example.com",
"department": "HR"
}
Partial Update (PATCH)
PATCH updates only specific fields.
class EmployeePartialUpdateAPIView(APIView):
def patch(self, request, pk):
employee = Employee.objects.get(pk=pk)
serializer = EmployeeSerializer(
employee,
data=request.data,
partial=True
)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors)
Request:
{
"department": "Finance"
}
Response:
{
"id": 1,
"name": "Tarun Kumar",
"email": "tarun@example.com",
"department": "Finance"
}
Delete Operation (DELETE)
Delete removes a record from the database.
from rest_framework import status
class EmployeeDeleteAPIView(APIView):
def delete(self, request, pk):
employee = Employee.objects.get(pk=pk)
employee.delete()
return Response(
{
"message": "Employee deleted successfully"
},
status=status.HTTP_204_NO_CONTENT
)
Request:
DELETE /api/employees/1/
Response:
{
"message": "Employee deleted successfully"
}
Complete CRUD API in a Single View
You can also combine all operations into one APIView.
from rest_framework.views import APIView
from rest_framework.response import Response
class EmployeeAPIView(APIView):
def get(self, request):
pass
def post(self, request):
pass
def put(self, request):
pass
def patch(self, request):
pass
def delete(self, request):
pass
However, for larger applications, separate views are usually easier to maintain.
URL Configuration
from django.urls import path
from .views import (
EmployeeListAPIView,
EmployeeDetailAPIView,
EmployeeCreateAPIView,
EmployeeUpdateAPIView,
EmployeeDeleteAPIView
)
urlpatterns = [
path(
'employees/',
EmployeeListAPIView.as_view()
),
path(
'employees/create/',
EmployeeCreateAPIView.as_view()
),
path(
'employees/<int:pk>/',
EmployeeDetailAPIView.as_view()
),
path(
'employees/<int:pk>/update/',
EmployeeUpdateAPIView.as_view()
),
path(
'employees/<int:pk>/delete/',
EmployeeDeleteAPIView.as_view()
),
]
CRUD and HTTP Methods
| Operation | HTTP Method |
|---|---|
| Create | POST |
| Read | GET |
| Update | PUT |
| Partial Update | PATCH |
| Delete | DELETE |
Best Practices
- Always use serializers for validation.
- Return meaningful status codes.
- Handle exceptions properly.
- Use
get_object_or_404()instead ofModel.objects.get(). - Keep business logic separate from views.
- Use Generic Views or ViewSets for large projects.
Conclusion
CRUD operations are the foundation of most REST APIs. Django REST Framework provides powerful tools such as APIView, serializers, and ModelSerializer to efficiently implement Create, Read, Update, and Delete functionality while maintaining clean and scalable code.