With Django Headless you quickly create a REST API for your models, making it easy to turn Django into a powerful headless CMS.
- π― Easy configuration: Add
@register
decorator to any model and get instant REST endpoints - π€ Plays nice: Seamlessly integrates with existing Django applications
- π Supports singletons: Special handling for singleton models (settings, configurations, etc.)
- π Flexible filtering: Optional filtering backend based on Django ORM lookups
- π‘οΈ Secure: Inherits Django's security features and permissions system
βοΈ Django Headless depends on Django and Django Rest Framework.
pip install django-headless
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'headless', # Add this
# ... your apps
]
REST_FRAMEWORK = {
# Optional: add the lookup filter backend
"DEFAULT_FILTER_BACKENDS": [
"headless.rest.filters.LookupFilter",
#...
# Optional: add the secret key authentication class
"DEFAULT_AUTHENTICATION_CLASSES": [
"headless.rest.authentication.SecretKeyAuthentication",
#... other DRF config
}
# models.py
from django.db import models
from headless import register
@register()
class BlogPost(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
published = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
# urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('headless.urls')),
]
That's it! π Your model is now available via REST API at /api/blog-post/
from headless import register
@register()
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
Generated endpoints:
GET /api/article/
- List all articlesPOST /api/article/
- Create new articleGET /api/article/{id}/
- Retrieve specific articlePUT /api/article/{id}/
- Update articlePATCH /api/article/{id}/
- Partially update articleDELETE /api/article/{id}/
- Delete article
Perfect for site settings, configurations, or any model that should have only one instance:
@register(singleton=True)
class SiteConfiguration(models.Model):
site_name = models.CharField(max_length=100)
maintenance_mode = models.BooleanField(default=False)
contact_email = models.EmailField()
class Meta:
verbose_name = "Site Configuration"
Generated endpoints:
GET /api/site-configuration/
- Get configurationPUT /api/site-configuration/
- Update configurationPATCH /api/site-configuration/
- Partial update
Django Headless supports Django ORM lookups for powerful filtering. Add the LookupFilter backend to your default filter backends:
REST_FRAMEWORK = {
"DEFAULT_FILTER_BACKENDS": [
"headless.rest.filters.LookupFilter",
#... other DRF config
}
Filter examples:
# Basic filtering
GET /api/blogpost/?published=true
# Field lookups
GET /api/blogpost/?title__icontains=django
GET /api/blogpost/?created_at__gte=2023-01-01
GET /api/blogpost/?author__username=john
# Multiple filters
GET /api/blogpost/?published=true&created_at__year=2023
Values are automatically cast based on the field type. Booleans can be represented
as true
, 1
or on
(and false
, 0
or off
). Multi-value lookups can be comma-separated (e.g. id__in=1,2,3
).
The @register
decorator accepts the following configuration options:
Option | Type | Default | Description |
---|---|---|---|
singleton |
bool |
False |
Creates singleton endpoints (no create, list and delete endpoints) |
# settings.py
HEADLESS = {
"AUTH_SECRET_KEY": None,
"AUTH_SECRET_KEY_HEADER": "X-Secret-Key",
"FILTER_EXCLUSION_SYMBOL": "~",
"NON_FILTER_FIELDS": [
"search",
"limit",
"page",
"fields",
"exclude",
"expand",
],
}
- Python 3.10+
- Django 5.0+
- Django REST Framework 3.16+
We welcome contributions! Here's how to get started:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Make your changes
- Add tests for your changes
- Run the test suite (
python manage.py test
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
# Clone the repository
git clone https://github.com/StructuralRealist/django-headless.git
cd django-headless
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements-dev.txt
# Run tests
python manage.py test
# Run example project
cd example_project
python manage.py migrate
python manage.py runserver
For detailed documentation, visit djangoheadless.org
- π Bug Reports: GitHub Issues
- π¬ Discussions: GitHub Discussions
- π§ Email: [email protected]
This project is licensed under the MIT License - see the LICENSE file for details.
- Built on the shoulders of Django and Django REST Framework
- Inspired by the headless CMS and Jamstack movement
- Thanks to all contributors and the Django community
Made in Europe πͺπΊ with π for Django