How do you use Django Rest Framework for the Activity Tracker Application?

Moise Lala
5 min readFeb 11, 2024

--

In the last post, I showed how you can set up Django as the backend for an activity tracker Application. In this post, I detailed how to extend the application in Django with Django Rest Framework.

Prerequisite

  • As mentioned in the post, create a Django project with a similar file structure.

Applications communicate with each other. They must agree on the information format to make communications comprehensible between them. One such format widely used is JSON.

Converting between an application format and JSON is called serializing, and going from JSON to application representation is called deserializing.

Django rest framework is an open-source app/package of Django that will allow us to pack and unpack the information in JSON from a Django Python representation.

To install Django rest framework, run this command:

pip install djangorestframework

Add rest framework to the INSTALLED_APPS in trackerBe/settings.py.

Makemigrations and migrate as we have done with the other installed apps.

Views and Serialize Goal app

Create a serializers.py file in the goal folder. And add the following content:

from rest_framework import serializers
from .models import Goal
class GoalSerializer(serializers.ModelSerializer):
class Meta:
model = Goal
fields = '__all__'

Open the views.py and add the following:

from django.shortcuts import get_object_or_404
from rest_framework import viewsets, status
from rest_framework.response import Response
from .models import Goal
from .serializers import GoalSerializer
class GoalViewSet(viewsets.ViewSet):
def list(self, request):
queryset = Goal.objects.all()
serializer = GoalSerializer(queryset, many=True)
return Response(serializer.data)
def create(self, request):
serializer = GoalSerializer(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)
def retrieve(self, request, pk=None):
queryset = Goal.objects.all()
goal = get_object_or_404(queryset, pk=pk)
serializer = GoalSerializer(goal)
return Response(serializer.data)
def update(self, request, pk=None):
queryset = Goal.objects.all()
get_object_or_404(queryset, pk=pk)
serializer = GoalSerializer(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)
def destroy(self, request, pk=None):
queryset = Goal.objects.all()
goal = get_object_or_404(queryset, pk=pk)
goal.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

This file has all the functions needed, such as:

  • List: this is to list all the goals in the Activity application.
  • Create: this is to create a goal in the Activity application.
  • Retrieve: this is to get a goal based on the id.
  • Update: this is to modify the existing goal in the Activity application.
  • Destroy: this removes the existing goal in the Activity application altogether.

To see the goals on the browser, create a urls.py file. Add the following content:

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import GoalViewSetrouter = DefaultRouter()
router.register(r'', GoalViewSet, basename='goal')
urlpatterns = [
path('', include(router.urls))
]

Finally, in the trackerBe/urls.py, add the content:

from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('goals/', include('goal.urls')),
]

Now everything is wired up. Go to the browser and navigate to localhost:8000/goals/

The following content should be seen (I created a goal in the admin site):

Views and Serialize Activity app

Same steps are done for the activity app.

In the activity folder, create the serializers.py and add:

from rest_framework import serializers
from .models import Activity
class ActivitySerializer(serializers.ModelSerializer):
class Meta:
model = Activity
fields = '__all__'

views.py content:

from django.shortcuts import get_object_or_404
from rest_framework import viewsets, status
from rest_framework.response import Response
from .models import Activity
from .serializers import ActivitySerializer
class ActivityViewSet(viewsets.ViewSet):
def list(self, request):
queryset = Activity.objects.all()
serializer = ActivitySerializer(queryset, many=True)
return Response(serializer.data)
def create(self, request):
serializer = ActivitySerializer(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)
def retrieve(self, request, pk=None):
queryset = Activity.objects.all()
activity = get_object_or_404(queryset, pk=pk)
serializer = ActivitySerializer(activity)
return Response(serializer.data)
def update(self, request, pk=None):
queryset = Activity.objects.all()
get_object_or_404(queryset, pk=pk)
serializer = ActivitySerializer(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)
def destroy(self, request, pk=None):
queryset = Activity.objects.all()
activity = get_object_or_404(queryset, pk=pk)
activity.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

urls.py content:

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ActivityViewSetrouter = DefaultRouter()
router.register(r'', ActivityViewSet, basename='activity')
urlpatterns = [
path('', include(router.urls))
]

Include activity urls in the trackerBe/url.py:

path('activities/', include('activity.urls')),

Navigate to localhost:8000/activities/ and view some activities or create one.

Views and Serialize Todo app

In the todo folder, create serializers.py with content:

from rest_framework import serializers
from .models import Todo, TodoItemclass TodoSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = '__all__'
class TodoItemSerializer(serializers.ModelSerializer):
class Meta:
model = TodoItem
fields = '__all__'

There are two serializers here, one for the to-do and the other to-do item.

In the todo views.py add the following:

from django.shortcuts import get_object_or_404
from rest_framework import viewsets, status
from rest_framework.response import Response
from .models import Todo, TodoItem
from .serializers import TodoSerializer, TodoItemSerializer
class TodoViewSet(viewsets.ViewSet): def list(self, request):
queryset = Todo.objects.all()
serializer = TodoSerializer(queryset, many=True)
return Response(serializer.data)
def create(self, request):
serializer = TodoSerializer(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)
def retrieve(self, request, pk=None):
queryset = Todo.objects.all()
todo = get_object_or_404(queryset, pk=pk)
serializer = TodoSerializer(todo)
return Response(serializer.data)
def update(self, request, pk=None):
queryset = Todo.objects.all()
get_object_or_404(queryset, pk=pk)
serializer = TodoSerializer(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)
def destroy(self, request, pk=None):
queryset = Todo.objects.all()
todo = get_object_or_404(queryset, pk=pk)
todo.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class TodoItemViewSet(viewsets.ViewSet): def list(self, request):
queryset = TodoItem.objects.all()
serializer = TodoItemSerializer(queryset, many=True)
return Response(serializer.data)
def create(self, request):
serializer = TodoItemSerializer(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)
def retrieve(self, request, pk=None):
queryset = TodoItem.objects.all()
todo_item = get_object_or_404(queryset, pk=pk)
serializer = TodoItemSerializer(todo_item)
return Response(serializer.data)
def update(self, request, pk=None):
queryset = TodoItem.objects.all()
get_object_or_404(queryset, pk=pk)
serializer = TodoItemSerializer(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)
def destroy(self, request, pk=None):
queryset = TodoItem.objects.all()
todo_item = get_object_or_404(queryset, pk=pk)
todo_item.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

Notice how they all seem similar, but the only differences are in the class called.

Create the urls.py and add the following content:

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import TodoViewSet, TodoItemViewSetrouter = DefaultRouter()
router.register(r'items', TodoItemViewSet, basename='todo_item')
router.register(r'', TodoViewSet, basename='todo')
urlpatterns = [
path('', include(router.urls)),
]

And in trackerBe/urls.py add:

path('todos/', include('todo.urls')),

Navigate to localhost:8000/todos/ to view the to-do lists and localhost:8000/todos/items/ to view the to-do list items

In my next article, I will create another application allowing users to interact with a more friendly user interface. This will be in React (Javascript web framework) and be called tracker-ui. These two applications together will form the Activity application.

Happy coding!

--

--