Django REST API - CRUD with DRF

Last Updated : 3 Jun, 2026

The article demonstrates building CRUD REST APIs using Django REST Framework (DRF) for a supermarket inventory system. It manages categories, subcategories, and products through RESTful endpoints that support creating, retrieving, updating, and deleting records.

Make sure Django is installed and configured before continuing. If not, refer to the following article for setup instructions: 

Django Introduction and Installation

Installation

Run the following command to install Django REST Framework:

pip install djangorestframework

install Django REST Framework

After installing the REST framework, go to settings.py, and in INSTALLED_APPS add ‘rest_framework’ at the bottom.

Python
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework', 
]

Creating App for Django REST Framework

Step 1: After installing DRF and adding it to settings.py, let's create an app using the command:

python manage.py startapp api

After executing the command, Django creates a new application named api within the project.

django api create app folder

Step 2: Add this app to INSTALLED_APPS and urls.py also in, settings.py.

Python
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'api.apps.ApiConfig',
]

Step 3: Add the api URL patterns to the project's urls.py file. In gfg_shopping/urls.py, include the following code:

Python
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('api.urls')),
]

Creating Model in Django

Create the Item model, which defines the data structure used by the API for CRUD operations.

Python
from django.db import models

class Item(models.Model):
    category = models.CharField(max_length=255)
    subcategory = models.CharField(max_length=255)
    name = models.CharField(max_length=255)
    amount = models.PositiveIntegerField()

    def __str__(self) -> str:
        return self.name

Now after app gets ready, create the serializer for Item class.

ModelSerializer

The Item model must be converted into a format that can be sent and received through API requests. ModelSerializer handles this conversion automatically by generating serializer fields from the model, allowing CRUD operations to be implemented with minimal code.

Now create serlializers.py file in the api folder.

Python
from django.db.models import fields
from rest_framework import serializers
from .models import Item

class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = ('category', 'subcategory', 'name', 'amount')

Create Views for Django

To render data into frontend, and handle requests from user, we need to create a view. In Django REST Framework, we call these viewsets, so create a view in apis/views.py,

Python
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Item
from .serializers import ItemSerializer

@api_view(['GET'])
def ApiOverview(request):
    api_urls = {
        'all_items': '/',
        'Search by Category': '/?category=category_name',
        'Search by Subcategory': '/?subcategory=category_name',
        'Add': '/create',
        'Update': '/update/pk',
        'Delete': '/item/pk/delete'
    }

    return Response(api_urls)

In the above code, the api_view decorator takes a list of HTTP methods that a views should response to. Other methods will response with the Method Not Allowed.

Update the api/urls.py file to register the API endpoints:

Python
from django.urls import path
from . import views

urlpatterns = [
    path('', views.ApiOverview, name='home')
]

With the API configuration complete, start the development server using the following commands:

python manage.py makemigrations
python manage.py migrate
python manage.py runserver

Now, head to http://127.0.0.1:8000/api/

django rest api view

CRUD Opetration with Django Rest Framework

Create View

To create new records through the API, define a view that handles POST requests. Add the following add_items function to views.py:

Python
from rest_framework import serializers
from rest_framework import status

@api_view(['POST'])
def add_items(request):
    item = ItemSerializer(data=request.data)

    # validating for already existing data
    if Item.objects.filter(**request.data).exists():
        raise serializers.ValidationError('This data already exists')

    if item.is_valid():
        item.save()
        return Response(item.data)
    else:
        return Response(status=status.HTTP_404_NOT_FOUND)

Register the create endpoint in urls.py so that incoming requests can be routed to the add_items view:

Python
from django.urls import path
from . import views

urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
]

Visit http://127.0.0.1:8000/api/create/

Django Rest Framework - Create View

Read View

To retrieve records from the database, create a view that handles GET requests. The view_items function returns all items by default and also supports filtering results based on category, subcategory, or item name.

In views.py

Python
@api_view(['GET'])
def view_items(request):
    
    
    # checking for the parameters from the URL
    if request.query_params:
        items = Item.objects.filter(**request.query_params.dict())
    else:
        items = Item.objects.all()

    # if there is something in items else raise error
    if items:
        serializer = ItemSerializer(items, many=True)
        return Response(serializer.data)
    else:
        return Response(status=status.HTTP_404_NOT_FOUND)

In urls.py

Python
from django.urls import path
from . import views

urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
    path('all/', views.view_items, name='view_items'),

]

Now visit http://127.0.0.1:8000/api/all/

Django Rest Framework - List View

Note: In addition to retrieving all records, the endpoint allows users to filter results by category or subcategory and search for specific items by name using query parameters.

If we visit http://127.0.0.1:8000/api/all/?category=food our search result will narrow down to: 

Django Rest Framework - List View filter search result

Update View

To modify existing records, create an update endpoint that identifies an item using its primary key and updates the submitted data. Add the following update_items function to views.py:

In views.py

Python
@api_view(['POST'])
def update_items(request, pk):
    item = Item.objects.get(pk=pk)
    data = ItemSerializer(instance=item, data=request.data)

    if data.is_valid():
        data.save()
        return Response(data.data)
    else:
        return Response(status=status.HTTP_404_NOT_FOUND)

In urls.py

Python
from django.urls import path
from . import views

urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
    path('all/', views.view_items, name='view_items'),
    path('update/<int:pk>/', views.update_items, name='update-items'),

]

Now head to http://127.0.0.1:8000/api/all/?name=potato

Django rest framework update view

Delete View

To remove records from the database, create a view that handles DELETE requests. The delete_items function deletes a specific item identified by its primary key.

In views.py

Python
@api_view(['DELETE'])
def delete_items(request, pk):
    item = get_object_or_404(Item, pk=pk)
    item.delete()
    return Response(status=status.HTTP_202_ACCEPTED)

In urls.py

Python
from django.urls import path
from . import views

urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
    path('all/', views.view_items, name='view_items'),
    path('update/<int:pk>/', views.update_items, name='update-items'),
    path('item/<int:pk>/delete/', views.delete_items, name='delete-items'),
    
]

Now visit http://127.0.0.1:8000/api/item/pk/delete/. See the below GIF for better understanding.

Django Rest Framework - Delete View

Making Authenticated API Requests

The CRUD examples shown above uses open endpoints for simplicity. In real-world applications, APIs are often secured using authentication mechanisms such as Token Authentication or JWT Authentication.

Once authentication is enabled, clients must include a valid token in the request headers.

Example: Fetching Student Records with Token Authentication

Python
curl -X GET http://127.0.0.1:8000/students/ \
-H "Authorization: Token your_token_here"

Output

[
{
"id": 1,
"name": "Mike",
"roll": 101,
"city": "New York"
}
]

Explanation:

  • The Authorization header contains the authentication token.
  • The API verifies the token before processing the request.
  • If the token is valid, the requested data is returned.
  • If the token is missing or invalid, the API responds with an authentication error.

Note: This tutorial focuses on implementing CRUD operations with Django REST Framework. To learn how to secure your API endpoints using token-based authentication, refer to the article Implement Token Authentication using Django REST Framework.

Comment