Skip to main content

🐍 Introduction

Django Headless turns Django into a headless CMS backend. Decorate a model with @expose() and a standard Django REST Framework API appears — with list, detail and CRUD endpoints, filtering, pagination and singleton support. No serializers, viewsets or URL wiring to write.

from django.db import models
from headless import expose

@expose()
class BlogPost(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
published = models.BooleanField(default=False)

This single decorator generates:

MethodRouteAction
GET/api/blog.blogpostList (filterable)
POST/api/blog.blogpostCreate
GET/api/blog.blogpost/1Retrieve
PUT/api/blog.blogpost/1Update
PATCH/api/blog.blogpost/1Partial update
DELETE/api/blog.blogpost/1Delete
Protected by default

Generated routes answer 403 for unauthenticated requests — exposed models are never accidentally public. See permissions for opening routes up.

✨ Why Django Headless?​

The primary use case is running Django as the backend of a JAMstack setup: Django serves content through this generated REST API, while the frontend lives elsewhere (Next.js, Astro, etc.). The API is designed to be predictable and read-friendly for such frontend consumers:

  • 🎯 Easy configuration — a decorator is all it takes
  • 🤝 Plays nice — integrates with existing Django applications
  • 💈 Singletons — settings and configuration objects as a single resource
  • 🔍 Flexible filtering — every supported ORM lookup, straight from the query string
  • 🛡️ Secure by default — generated routes require authentication until you open them up
  • ⚡ Predictable — stable ordering, pagination envelope, and validation with clear errors

🧭 What's next?​

Read the installation guide to get your first headless model running in minutes.