Fastest way to create REST APIs in Django and Python: With Djapy

Bishwas Bhandari
3 min readSep 25


Today we’re learning about a fast and simple way to create REST APIs using Djapy, a useful tool for people who use Django and Python. Prior knowledge in Django and Python will help through the process. In the end, I’ll also share a GitHub repo where you can see and use all the code from this guide. Let’s start learning about Djapy!

In line with the philosophy of Django, Djapy emphasizes simplicity, flexibility, and efficiency. It acts as a tool to effortlessly create RESTful APIs with Django and Python without unnecessary complexity.

What is Djapy?

Djapy is a powerful library that enhances the Django framework. It’s designed to free developers from the need for boilerplate code when creating RESTful APIs. It upholds Django’s principle of “batteries included”, meaning it comes fully equipped with all the necessary features to handle most use cases.

However, Djapy stands out with its philosophy of “Do not use a Framework inside an awesome Framework”. This means it works seamlessly within Django, without imposing any specific design patterns. Its strength lies in its flexibility and ease of use, making the process of developing APIs simpler and more efficient.

Getting Started with REST API development

Let’s write a Todo API with authentication using Django’s Djapy. We will be doing CRUD API dev in this tutorial, but for this part, we will be just doing GET [with paginator] and POST [create], and will continue development on the next part [i.e. part 2].

Create a Django project todo and start an app named plans inside it.

django-admin srartproject todo
cd todo
django-admin startapp plans

Now, add plans inside the INSTALLED_APPS ,


Now, inside plans create

from django.contrib.auth import get_user_model
from django.db import models

class Todo(models.Model):
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
title = models.CharField(max_length=100)
completed_at = models.DateTimeField(null=True, blank=True)
dismissed_at = models.DateTimeField(null=True, blank=True)
will_be_completed_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __str__(self):
return self.title

## and remember to migrate it

Now, in plans/ , let’s create an GET API with paginator on it.

I am a big fan of functional programming, but if you want you can do it in a class-based way as well, have a look a docs if you want.

from djapy.pagination.dec import djapy_paginator

'id', 'title', 'will_be_completed_at', 'created_at',
'username', 'completed_at'
def todo_get(request, *args, **kwargs):
todos = Todo.objects.all()
todos = todos.filter(user=request.user).order_by('-completed_at')
return todos

And now create a POST API to create todos.

from import input_required
from djapy.pagination.dec import djapy_paginator

@input_required(['title', 'will_be_completed_at'], allow_empty_payloads=False)
@model_to_json_node(['id', 'title', 'will_be_completed_at', 'created_at'])
def todo_post(request, data):
todo = Todo.objects.create(
return todo

Now, we do need to assign these views to URLs. There are two function-based approaches, one we can assign each URL with each view or, we can assign each method with each view. Let’s do the each-method one.

from djapy.wrappers.dec import method_to_view, node_to_json_response
from django.views.decorators.csrf import csrf_exempt
from djapy.auth.dec import djapy_login_required

# Use @djapy_login_required if you want the API to be secure.
def todo_view(request):
return {
'post': todo_post,
'get': todo_get

Now, ;

from django.urls import path
from plans import views as plans_views

urlpatterns = [
path('todos/', plans_views.todo_view, name='todo-index')

Done. Now you can call each APIs with their relative method, and see the magic.

Next, we will do PATH request, GET [Each id details] with authorization and authentication.

Thanks :)



Bishwas Bhandari

I am a simple boy with a great passion for programming and computing concepts from Nepal. I describe myself as a crazy and logical coder.