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

Prashant Adhikari
Aug 28, 20253 min read
Prereqs
python --version # must be 3.10–3.13 for Django 5.2
pip --version1) 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 useAuthorization: Bearer <access>). PyPICRUD: 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)
Create a database, then set in
.env:
DATABASE_URL=postgresql://<user>:<pass>@localhost:5432/<db>
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
