<prashantAdhikari />
  • projects
  • skills
  • education
  • contact
  • Blogs

Prashant Adhikari

Full Stack Developer passionate about creating innovative web solutions.

Quick Links

ProjectsSkillsEducationContact

Connect

© 2026 Prashant Adhikari. All rights reserved.

All blogs

How to make project from Django Rest Framework for Beginner. ?

Prashant Adhikari

Prashant Adhikari

Aug 28, 20253 min read

Prereqs

python --version   # must be 3.10–3.13 for Django 5.2
pip --version

1) Create project & virtual env

# macOS/Linux
mkdir drf-starter && cd drf-starter
python -m venv .venv
source .venv/bin/activate

# Windows (PowerShell)
# mkdir drf-starter; cd drf-starter
# python -m venv .venv
# .\.venv\Scripts\Activate.ps1

2) Install packages (stable)

python -m pip install --upgrade pip

pip install \
  "Django==5.2.*" \
  "djangorestframework==3.16.*" \
  djangorestframework-simplejwt \
  drf-spectacular \
  django-cors-headers \
  django-environ
# Optional (PostgreSQL later): 
pip install "psycopg[binary]"

Why these:

  • DRF 3.16.x = current stable; supports Django 5.2/Python 3.13. Django REST Framework

  • SimpleJWT for stateless auth (latest 5.5.x). PyPI

  • drf-spectacular for OpenAPI/Swagger docs. DRF SpectacularPyPI

  • django-cors-headers to talk to your Next.js frontend. PyPI

  • psycopg installs the modern PostgreSQL driver (psycopg3). PyPI


3) Start Django project & app

django-admin startproject config .
python manage.py startapp api

4) Settings (secure, minimal)

Open config/settings.py and make these edits.

4.1 Add apps & middleware

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    # third-party
    "rest_framework",
    "corsheaders",
    "drf_spectacular",
    # local
    "api",
]

MIDDLEWARE = [
    "corsheaders.middleware.CorsMiddleware",  # put near top
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

4.2 Environment variables (with django-environ)

Create .env beside manage.py:

DEBUG=True
SECRET_KEY=change-me
ALLOWED_HOSTS=127.0.0.1,localhost
CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
DATABASE_URL=sqlite:///db.sqlite3

At the very top of config/settings.py:

from pathlib import Path
import environ

BASE_DIR = Path(__file__).resolve().parent.parent

env = environ.Env(DEBUG=(bool, False))
environ.Env.read_env(BASE_DIR / ".env")

DEBUG = env("DEBUG")
SECRET_KEY = env("SECRET_KEY")
ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", default=[])
CORS_ALLOWED_ORIGINS = env.list("CORS_ALLOWED_ORIGINS", default=[])

django-environ lets you read lists like ALLOWED_HOSTS cleanly. django-environ.readthedocs.ioPyPI

4.3 Database

DATABASES = {"default": env.db("DATABASE_URL", default=f"sqlite:///{BASE_DIR/'db.sqlite3'}")}

(If you later set DATABASE_URL=postgresql://user:pass@host:5432/dbname, psycopg will be used.) PyPI

4.4 DRF defaults (JSON, pagination, JWT, schema)

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework_simplejwt.authentication.JWTAuthentication",
    ),
    "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
    "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
    "PAGE_SIZE": 10,
    "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
}

SPECTACULAR_SETTINGS = {
    "TITLE": "DRF Starter API",
    "DESCRIPTION": "Minimal Django REST Framework starter with JWT and OpenAPI docs.",
    "VERSION": "1.0.0",
}

DRF 3.16 config + drf-spectacular schema class. Django REST FrameworkDRF Spectacular

4.5 Static files (optional production helper)

If you plan to serve static files directly from Django (e.g., on Heroku), add WhiteNoise later:

pip install whitenoise
MIDDLEWARE.insert(1, "whitenoise.middleware.WhiteNoiseMiddleware")
STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"

(WhiteNoise supports Django 5.2.) WhiteNoise+1


5) URL routes (API + docs + JWT)

config/urls.py:

from django.contrib import admin
from django.urls import path, include
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView

urlpatterns = [
    path("admin/", admin.site.urls),
    # OpenAPI schema & Swagger UI
    path("api/schema/", SpectacularAPIView.as_view(), name="schema"),
    path("api/docs/", SpectacularSwaggerView.as_view(url_name="schema"), name="docs"),
    # JWT
    path("api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"),
    path("api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
    # Your app
    path("api/", include("api.urls")),
]

(drfs-pectacular simple setup). DRF Spectacular


6) Build your first API (Todo example)

api/models.py

from django.db import models

class Todo(models.Model):
    title = models.CharField(max_length=200)
    done = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

api/serializers.py

from rest_framework import serializers
from .models import Todo

class TodoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Todo
        fields = ["id", "title", "done", "created_at"]

api/views.py

from rest_framework import viewsets, permissions
from .models import Todo
from .serializers import TodoSerializer

class TodoViewSet(viewsets.ModelViewSet):
    queryset = Todo.objects.order_by("-created_at")
    serializer_class = TodoSerializer
    permission_classes = [permissions.IsAuthenticated]

api/urls.py

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import TodoViewSet

router = DefaultRouter()
router.register(r"todos", TodoViewSet, basename="todo")

urlpatterns = [path("", include(router.urls))]

7) Migrate, create superuser, run

python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
  • Swagger docs: http://127.0.0.1:8000/api/docs/ (auto from drf-spectacular). DRF Spectacular

  • Obtain JWT: POST {"username":"...", "password":"..."} → /api/token/ (then use Authorization: Bearer <access>). PyPI

  • CRUD: use /api/todos/.

Example (after getting a token):

curl -H "Authorization: Bearer <ACCESS>" http://127.0.0.1:8000/api/todos/

8) Enable CORS for your Next.js frontend

You already set CORS_ALLOWED_ORIGINS in .env. That’s it for typical setups. (Package docs here.) PyPI


9) Switch to PostgreSQL (later)

  1. Create a database, then set in .env:

DATABASE_URL=postgresql://<user>:<pass>@localhost:5432/<db>
  1. Install psycopg (already done above) and run migrations again. PyPI


10) (Nice to have) Tests & quality

pip install pytest pytest-django ruff black

pytest.ini

[pytest]
DJANGO_SETTINGS_MODULE = config.settings
python_files = tests.py test_*.py *_tests.py

Run tests with pytest. pytest-django.readthedocs.io+1

Thanks for reading — share it if it helped.

Prashant Adhikari

Written by

Prashant Adhikari

Full-stack engineer writing about the things I build, break and eventually fix.

Get in touch

On this page

  • Prereqs
  • 4.1 Add apps & middleware
  • 4.2 Environment variables (with django-environ)
  • 4.3 Database
  • 4.4 DRF defaults (JSON, pagination, JWT, schema)
  • 4.5 Static files (optional production helper)

Keep reading

All posts

My Office Made me Full Stack Developer because of Claude

am I tripping ?

Jul 27, 2026

Forward Ref is Depreciated in React 19

Forward Ref a Really Game Changer

Jul 27, 2026

How I Built CaloGlow: An AI Calorie Tracker That Actually Understands Dal Bhat

CaloGlow - Only Calories Tracker You Need

Jul 27, 2026

Back to all blogs