Create a django todo app using django-rest-framework.

In this tutorial, you will be learning how to create a todo app using Django/Python and drf (django rest framework).


Let's get started:

We have to install some tools:

I will assume you already have pip and python installed.

pip install pipenv - to install a virtual environment.
pipenv shell - creates/springs up a virtual environment for your app.
pipenv install django~=3.1.0 - to install the django package.
pipenv install djangorestframework~=3.11 - to install the django rest framework.
pipenv install psycopg2~=2.8.5- for database connection.

Run django-admin startproject <name of app> - creates a new app folder with its config/settings/details.

I will assume that you have postgres installed, create a new database called: todoapp and add the following piece of code to the .env file.

db_name=todoapp
db_user=<postgres-user>
db_password=<postgres-password>

Then in the settings file,

Add the following piece of code for database connectivity:

import os - at the top of the file.

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - to build the path.

  • replace the database configuration with the following piece of code to enable us use postgres.
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': os.getenv('db_name'),
        'PASSWORD': os.getenv('db_password'),
        'USER': os.getenv('db_user'),
        'PORT': '5432',
        'HOST': 'localhost'
    }
}

add rest_framework and todoapp - to the INSTALLED_APPS right under the other ones there.

INSTALLED_APPS = [
    'rest_framework',
    'todoapp'
]

cd into the newly created app/folder(todoapp) and run

  • python manage.py makemigrations todoapp to migrate and propagate new changes.
  • python manage.py migrate todoapp to migrate files into the database
  • python manage.py runserver to start up the server. You can view this in your browser using the url.

In the todoapp folder, where the settings file is, create a new file called models.py and add the following code:

from django.db import models

class NoteModel(models.Model):

    title = models.CharField(max_length=100)
    description = models.CharField(max_length=200)
    tags = models.CharField(max_length=300)

    def __str__(self):
        return self.title

Note:

create another file called serializers.py and add the following code:

from django.contrib.postgres.fields import ArrayField
from rest_framework import serializers
from .models import NoteModel

class NoteSerializer(serializers.ModelSerializer):

    title = serializers.CharField(max_length=100)
    description = serializers.CharField(max_length=200)
    tags = ArrayField(
        serializers.CharField(max_length=300), default=list)

    class Meta:
        model = NoteModel
        fields = ['title', 'description', 'tags']

Note:

  • the ArrayField is imported to enable us to add an array of items(tags) to the database.
  • serializers are imported from django rest framework.
  • also, the created model is imported.
  • we declare serializers that can help us to serialize data.

create another file called views.py and add the following code:

from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import NoteModel
from .serializers import NoteSerializer

class NoteView(APIView):

    """
    Create a new note
    """

    def post(self, request):
        serializer = NoteSerializer(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)

    """
    Get all notes
    """

    def get(self, request):
        notes = NoteModel.objects.all()
        serializer = NoteSerializer(notes, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


class NoteDetailView(APIView):

    """
    Get a note
    """

    def get_object(self, pk):
        try:
            return NoteModel.objects.get(pk=pk)
        except NoteModel.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        note = self.get_object(pk)
        serializer = NoteSerializer(note)
        return Response(serializer.data)

    """
    Update a note
    """

    def put(self, request, pk, format=None):
        note = self.get_object(pk)
        serializer = NoteSerializer(note, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)    

    """
    Delete a note
    """

    def delete(self, request, pk, format=None):
        note = self.get_object(pk)
        note.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Note:

  • we are making use of the django rest framework's class-based views.
  • the created models and serializers are created.
  • two classes are created called NoteView and NoteDetailView.
  • for the class NoteView, two methods are created for post to create a new note and get to get all notes.
  • then for the class NoteDetailView, three methods are created forput to update a note, delete to delete a note and get to get a single note.

Read more about the methods on the official docs: django-rest-framework.org/tutorial/3-class-..

We have to create URLs for the created methods, add the following code:

from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from .views import NoteView, NoteDetailView

urlpatterns = [
    path('notes', NoteView.as_view()),
    path('note/<int:pk>', NoteDetailView.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

Run python manage.py runserver to start your server and test the endpoints.

For the code repo: github.com/codeliezel/django-drf-todo

That marks the end of this tutorial.