
How to Build a REST API in Django
How to Build a REST API in Django êŽë š
If youâre building a web or mobile app, chances are youâre going to need a way to send and receive data between your app and a server.
Thatâs where REST APIs come in. They help apps talk to each other â kind of like a waiter taking your order and bringing your food back. And if you're using Django, you're already halfway there.
Django is one of the most popular web frameworks out there. Itâs fast, secure, and packed with useful tools. Combine it with Django REST Framework (DRF), and youâve got everything you need to build a solid REST API without spending weeks figuring it all out.
In this guide, Iâll walk you through the whole process of building a REST API in Django from scratch.
What is a REST API?
Before we get started, letâs get one thing straight: Whatâs even is a REST API?
A REST API (short for âRepresentational State Transferâ) is a way for two systems â like a website and a server â to talk to each other using standard HTTP methods like GET, POST, PUT, and DELETE.
Letâs say you have a to-do app. You want to:
- Get a list of tasks
- Add a new task
- Update a task
- Delete a task
You can do all of that through a REST API. Itâs like setting up your own menu of commands that other apps (or your frontend) can use to work with your data.
Tools Youâll Need:
Hereâs what youâll be using in this tutorial:
- Python (preferably 3.8+)
- Django (web framework)
- Django REST Framework (DRF) (to build APIs)
- Postman or curl (for testing)
You can install DRF with:
pip install djangorestframework
How to Build a REST API in Django
Here is how to get started:
Step 1: Set Up Your Django Project
If you havenât already, start a new Django project:
django-admin startproject myproject
cd myproject
python manage.py startapp api
django-admin startproject myproject
â Creates a new Django project namedmyproject
, which contains configuration files for your whole site.cd myproject
â Move into your new project directory.python manage.py startapp api
â Creates a new Django app namedapi
where your models, views, and API logic will live.
Now add 'rest_framework'
and 'api'
to your INSTALLED_APPS
in settings.py
:
INSTALLED_APPS = [
...
'rest_framework',
'api',
]
rest_framework
is the Django REST Framework â it gives you tools to easily create APIs.'api'
tells Django to look in theapi
folder for models, views, and so on.
Step 2: Create a Model
Letâs make a simple model â a task list.
In api/
models.py
:
from django.db import models
class Task(models.Model):
title = models.CharField(max_length=200)
completed = models.BooleanField(default=False)
def __str__(self):
return self.title
title
: A short piece of text (like âBuy groceriesâ).CharField
is used for strings.completed
: A Boolean (True or False) to mark if a task is done.__str__
: This special method returns a string version of the model when printed â useful for debugging and the admin panel.
Then run:
python manage.py makemigrations
python manage.py migrate
makemigrations
: Prepares the changes to the database schema.migrate
: Applies those changes to the actual database.
Step 3: Make a Serializer
Serializers turn your Django model into JSON (the data format used in APIs) and back.
In api/
serializers.py
:
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = '__all__'
- Serializers convert model instances (like a
Task
) to and from JSON, so they can be sent over the web. ModelSerializer
is a shortcut that automatically handles most things based on your model.fields = '__all__'
means include every field in the model (title and completed).
Step 4: Create the Views
Hereâs where the logic goes. You can use class-based or function-based views. Letâs go with class-based using DRFâs generics
.
In api/
views.py
:
from rest_framework import generics
from .models import Task
from .serializers import TaskSerializer
class TaskListCreate(generics.ListCreateAPIView):
queryset = Task.objects.all()
serializer_class = TaskSerializer
class TaskDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Task.objects.all()
serializer_class = TaskSerializer
These are generic class-based views provided by Django REST Framework to save you time.
TaskListCreate
:- Handles GET requests to list all tasks.
- Handles POST requests to create new tasks.
TaskDetail
:- Handles GET for one task, PUT/PATCH for updating, and DELETE to remove a task
Step 5: Set Up URLs
First, make a urls.py
file in the api
folder (if it doesnât exist).
In api/
urls.py
:
from django.urls import path
from .views import TaskListCreate, TaskDetail
urlpatterns = [
path('tasks/', TaskListCreate.as_view(), name='task-list'),
path('tasks/<int:pk>/', TaskDetail.as_view(), name='task-detail'),
]
tasks/
: The route to access or create tasks.tasks/<int:pk>/
: The route to get, update, or delete a single task by its primary key (pk
).
Then, in your main myproject/
urls.py
:
Now, hook this into the main urls.py
in your project folder:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls')),
]
Step 6: Test It!
Start the server:
python manage.py runserver
Open Postman or curl and try hitting these endpoints:
GET /api/tasks/
â get all tasksPOST /api/tasks/
â create a new taskGET /api/tasks/1/
â get a specific taskPUT /api/tasks/1/
â update a taskDELETE /api/tasks/1/
â delete a task
And thatâs it â youâve got a working REST API.
This setup gives you a fully functional REST API with just a few lines of code, thanks to Django REST Framework. You should now understand:
- How models define your database structure
- How serializers turn models into JSON and vice versa
- How views control API behaviour (get, post, update, delete)
- How URL routing connects your views to web requests
DRF Permissions
Right now, anyone can use your API. But what if you only want certain users to have access?
DRF gives you simple ways to handle this. For example, to make an API only available to logged-in users:
from rest_framework.permissions import IsAuthenticated
class TaskListCreate(generics.ListCreateAPIView):
...
permission_classes = [IsAuthenticated]
There are more permissions you can use, like IsAdminUser
custom permissions, for example.
Letâs break this down and go deeper into permissions in Django REST Framework (DRF), including:
What are Permissions in DRF?
Permissions in DRF control who can access your API and what actions they can perform (read, write, delete, etc.).
Theyâre applied per view (or viewset), and they're checked after authentication, meaning they build on top of checking whether the user is logged in.
Common Built-In Permissions
DRF gives you a few super useful built-in permission classes out of the box:
1. IsAuthenticated
This one ensures that only logged-in users can access the view:
from rest_framework.permissions import IsAuthenticated
class TaskListCreate(generics.ListCreateAPIView):
queryset = Task.objects.all()
serializer_class = TaskSerializer
permission_classes = [IsAuthenticated]
Only users who have been authenticated (for example, via session login or token) will be able to list or create tasks. Anyone else gets a 403 Forbidden
response.
2. IsAdminUser
Only allows access if user.is_staff
is True
.
from rest_framework.permissions import IsAdminUser
class AdminOnlyView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [IsAdminUser]
Only admin users (usually set via Django admin or superuser status) can access this view.
3. AllowAny
Allows all users, even unauthenticated ones. This is the default for open APIS like sign-up pages.
from rest_framework.permissions import AllowAny
class PublicSignupView(generics.CreateAPIView):
serializer_class = SignupSerializer
permission_classes = [AllowAny]
4. IsAuthenticatedOrReadOnly
Authenticated users can read and write, unauthenticated users can only read (GET, HEAD, OPTIONS).
from rest_framework.permissions import IsAuthenticatedOrReadOnly
class ArticleView(generics.RetrieveUpdateAPIView):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
Use case: Great for blogs or article APIS where the public can read but only registered users can write/update.
Custom Permissions
Want more control? You can create your permissions by subclassing BasePermission
.
Example: Only allow owners of an object to edit it
from rest_framework.permissions import BasePermission
class IsOwner(BasePermission):
def has_object_permission(self, request, view, obj):
return obj.owner == request.user
Then use it like this:
class TaskDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Task.objects.all()
serializer_class = TaskSerializer
permission_classes = [IsAuthenticated, IsOwner]
- First, a user must be logged in (
IsAuthenticated
). - Then, only the owner of that specific
Task
can view, update, or delete it.
Combining Permissions
You can combine multiple permission classes, and all must return True
for access to be granted.
permission_classes = [IsAuthenticated, IsAdminUser]
This means: user must be both authenticated and an admin.
TL;DR
Permission | Who Gets Access? |
---|---|
AllowAny | Everyone (even logged-out users) |
IsAuthenticated | Only logged-in users |
IsAdminUser | Only admin/staff users |
IsAuthenticatedOrReadOnly | Read: everyone / Write: only logged-in users |
Custom Permissions | Your rules (e.g., only owners) |
FAQs
Do I need Django REST Framework to build an API in Django?
Technically, no â but DRF makes your life much easier. Without DRF, you'd have to manually handle things like:
- Parsing and validating JSON requests
- Writing views to serialise Python objects to JSON
- Managing HTTP status codes and responses
- Handling authentication and permissions on your own
In short, youâd be reinventing the wheel â but DRF does all of this for you with far less code.
Can I use this API with a React or Vue frontend?
Absolutely. Your Django API will send and receive data in JSON format â which is exactly what modern frontend frameworks like React and Vue are designed to work with. Just make sure you handle CORS (Cross-Origin Resource Sharing) correctly.
How do I make my API faster?
You can:
- Use caching to store frequent responses
- Enable pagination to reduce data load
- Explore async views (Django 3.1+ supports async) for faster I/O
DRF also offers built-in tools for pagination, throttling, and more performance tweaks out of the box.
Final Thoughts
Building a REST API in Django might sound like a big job, but itâs just a series of small, manageable steps.
Once youâve done it once, it gets way easier the next time. Plus, using Django REST Framework saves a ton of timeâyouâre not reinventing the wheel every time.
Further Resources
Want to keep learning? Here are a few solid places to dig deeper: