-
Notifications
You must be signed in to change notification settings - Fork 0
Writing Endpoints in Django Rest Framework (DRF)
To create an endpoint in a Django REST Framework (DRF) project, follow these steps:
Every React project has multiple apps inside it. In our case these are accounts, api, foods
and project
holds setup for the whole project. In this example we will work on foods
.
/backend
/accounts
...
views.py
urls.py
/api
...
views.py
urls.py
/foods
...
views.py
urls.py
/project
settings.py
urls.py
wsgi.py
asgi.py
manage.py
Create a view that inherits from APIView
. Define HTTP method handlers (get
, post
, etc.) as methods.
Also don't forget to add different HTTP status' in your response. For example if no record is found return an error message so that client will understand there is no data, etc. This is not the best example but you got the point.
You can find information about HTTP codes at the end of this document.
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework import status
from .models import FoodEntry
from .serializers import FoodEntrySerializer
class FoodCatalog(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
"""
GET /foods/get_foods
Returns all FoodEntry instances from the database.
- 200 OK if any foods exist
- 404 Not Found if no entries are available
Requires JWT token in Authorization header.
"""
foods = FoodEntry.objects.all()
if foods.exists():
serializer = FoodEntrySerializer(foods, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(
{"detail": "No food entries found."},
status=status.HTTP_404_NOT_FOUND
)
Use the permission_classes
attribute to define access control.
- If the method is required to be user authentication(that means if a user must be logged in for that functionality you must use IsAuthenticated.
permission_classes = [AllowAny] # or [IsAuthenticated]
Map the view to a route in your Django app's urls.py
file (e.g., inside the foods
app):
from django.urls import path
from .views import FoodCatalog
urlpatterns = [
path("get_foods", FoodCatalog.as_view(), name="get_foods"),
]
In your project's main urls.py
, the app’s URLs is included under a path prefix, such as `foods/'.
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("api/", include("api.urls")),
path("users/", include("accounts.urls")),
path("users/", include("django.contrib.auth.urls")),
path("foods/", include("foods.urls")),
]
This means the full URL path to your endpoint will be:
http://localhost:8081/foods/get_foods
The URL must include the app name (foods/
) because all app-level URLs are merged into the main project under their designated path prefixes.
Start the Django server and test the endpoint using curl
or a browser.
curl http://localhost:8081/foods/get_foods
If running inside a container, ensure the correct port mapping is applied (e.g., -p 8081:8081
).
Here is an example model class that you can find in repo. Models are the Python classes that stands for DB tables, that we add fields, their types, and other attributes and constraints. If you need to add any seperate table object in your endpoint you can create it as follows, then we will handle DB migrations.
from django.db import models
class FoodEntry(models.Model):
name = models.CharField(max_length=100)
category = models.CharField(max_length=50)
serving_size = models.PositiveIntegerField(help_text="In grams")
calories_per_serving = models.FloatField()
protein_content = models.FloatField()
fat_content = models.FloatField()
carbohydrate_content = models.FloatField()
allergens = models.JSONField(default=list, blank=True) # e.g., ["Peanuts", "Gluten"]
dietary_options = models.JSONField(default=list, blank=True) # e.g., ["Vegan", "Vegetarian"]
nutrition_score = models.PositiveIntegerField()
image_url = models.URLField(blank=True)
def __str__(self):
return self.name
Here is an example serializer that maps helps mapping raw data into Python object, which is useful when we convert request parameters into a model object so that we can use ORM to use it in database operations.
from rest_framework import serializers
from .models import FoodEntry
class FoodEntrySerializer(serializers.ModelSerializer):
class Meta:
model = FoodEntry
fields = '__all__' # or list only specific fields
Here are the exampe ORM methods that you can used to fetch, delete, or insert data into database that will probably be used in your services or APIs mostly.
# fetches all the data
foods = FoodEntry.objects.all()
# fetches all the data with a constraint with a field etc. for example here all rows which has category fruit will be fetched.
fruits = FoodEntry.objects.filter(category="Fruit")
# here is basically an insertion into DB.
FoodEntry.objects.create(
name="Avocado",
category="Fruit",
serving_size=100,
calories_per_serving=160,
protein_content=2.0,
fat_content=15.0,
carbohydrate_content=9.0,
allergens=[],
dietary_options=["Vegan", "Vegetarian"],
nutrition_score=92,
image_url="https://example.com/avocado.jpg"
)
Below are the five most frequently used HTTP status codes, especially in Django REST Framework APIs:
- Meaning: The request was successful.
-
Use case: Standard response for successful
GET
,PUT
, orDELETE
operations. - Example: Returning a list of food entries.
- Meaning: A new resource was successfully created.
-
Use case: After a successful
POST
request (e.g., creating a new user or food item). - Example: Returning the newly created food entry.
- Meaning: The request is malformed or missing required data.
- Use case: When the client sends invalid JSON or fails validation checks.
-
Example: Missing
name
field in the payload.
- Meaning: Authentication is required or token is invalid.
- Use case: JWT token is missing or expired.
- Example: User attempts to access a protected endpoint without logging in.
- Meaning: The requested resource could not be found.
- Use case: Trying to retrieve or delete a food entry that doesn't exist.
-
Example:
GET /foods/999
when ID 999 doesn't exist.


-
Use Cases:
- Template
- Scenario 1: Community Sharing
- Scenario 2: For a Dietitian
- Scenario 3: Maintaining a Personal Inventory (as a Producer)
- Scenario 4: Proposing a Product and Adding a Recipe to Weekly Meal Plan
- Scenario 5: Creating a Meal Plan
- Scenario 6: Resetting Password
- Scenario 7: Moderator Actions
- Scenario 8: Searching for and Proposing a New Food Item
- Scenario 9: Budget-Conscious Grocery Shopping
- Scenario 10: Creating a New Store
- Scenario 11: User Profile Management
- Git: In a Nutshell
- Example GitHub Repositories
- System Modeling & UML
- Frontend Tutorial
- Frontend Roadmap
- Frontend Styling Guide
- Docker Summary
- Writing Endpoints
- Yusuf AKIN
- Arda SAYGAN
- Fatih Furkan Bilsel
- Berk GOKTAS
- Berkay BILEN
- Yusuf Anıl YAZICI
- Taha Topaloglu
- Nuri Basar
- Onur Kucuk
- Hasancan Keles
- Mete Damar