Automagically create a REST API for your Django models
Project description
Django Headless
With Django Headless you quickly create a REST API for your models, making it easy to turn Django into a powerful headless CMS.
✨ Features
- 🎯 Easy configuration: Add
@exposedecorator 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
🚀 Quick Start
Installation
☝️ Django Headless depends on Django and Django Rest Framework.
pip install django-headless
Add to Django Settings
# 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
}
Create Your First Headless Model
# apps/blog/models.py
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)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
Add URLs
# 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.blogpost/
📖 Usage Examples
Basic Model Registration
# apps/blog/models.py
from django.db import models
from headless import expose
@expose()
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey("user.User", on_delete=models.CASCADE)
Generated endpoints:
GET /api/blog.article/- List all articlesPOST /api/blog.article/- Create new articleGET /api/blog.article/{id}/- Retrieve specific articlePUT /api/blog.article/{id}/- Update articlePATCH /api/blog.article/{id}/- Partially update articleDELETE /api/blog.article/{id}/- Delete article
Singleton Models
Perfect for site settings, configurations, or any model that should have only one instance:
# apps/config/models.py
from django.db import models
from headless import expose
@expose(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/config.siteconfiguration/- Get configurationPUT /api/config.siteconfiguration/- Update configurationPATCH /api/config.siteconfiguration/- Partial update
Advanced Filtering
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/blog.blogpost/?published=true
# Field lookups
GET /api/blog.blogpost/?title__icontains=django
GET /api/blog.blogpost/?created_at__gte=2023-01-01
GET /api/blog.blogpost/?author__username=john
# Multiple filters
GET /api/blog.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).
🎛️ Configuration Options
The @expose decorator accepts the following configuration options:
| Option | Type | Default | Description |
|---|---|---|---|
singleton |
bool |
False |
Creates singleton endpoints (no create, list and delete endpoints) |
search_fields |
List[str] |
All the model's CharFields | Allows you to overwrite the allowed search fields. |
Global Settings
# settings.py
HEADLESS = {
"AUTH_SECRET_KEY": None,
"AUTH_SECRET_KEY_HEADER": "X-Secret-Key",
"FILTER_EXCLUSION_SYMBOL": "~",
"FILTER_TRUE_VALUES": ["true", "1", "on"],
"FILTER_FALSE_VALUES": ["false", "0", "off"],
"FILTER_NULL_VALUES": ["null", "none", "empty"],
"NON_FILTER_FIELDS": [
"search",
"limit",
"page",
"fields",
"omit",
"expand",
"ordering"
],
}
🛠️ Requirements
- Python 3.12+
- Django 5.0+
- Django REST Framework 3.16+
🤝 Contributing
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
Development Setup
# Clone the repository
git clone https://github.com/BitsOfAbstraction/django-headless.git
cd django-headless
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
poetry install
# Run tests
poetry run test
# Run example project
cd example_project
python manage.py migrate
python manage.py runserver
📚 Documentation
For detailed documentation, visit djangoheadless.org
🐛 Issues & Support
- 🐛 Bug Reports: GitHub Issues
- 💬 Discussions: GitHub Discussions
- 📧 Email: leon@devtastic.io
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- 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
🔗 Links
Made in Europe 🇪🇺 with 💚 for Django
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_headless-1.0.0rc1.post1.tar.gz.
File metadata
- Download URL: django_headless-1.0.0rc1.post1.tar.gz
- Upload date:
- Size: 17.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.2 CPython/3.13.12 Darwin/25.3.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8ffbca4b101ad4eb4737592e3b33bba2d284617327cc6b8255d8261c0013db2
|
|
| MD5 |
f383148915b693e50da1442fbf708b4f
|
|
| BLAKE2b-256 |
e9ec2612d800cc101ebcc3a945f2d1e2a41bd03f6115485d1771e15a1b886572
|
File details
Details for the file django_headless-1.0.0rc1.post1-py3-none-any.whl.
File metadata
- Download URL: django_headless-1.0.0rc1.post1-py3-none-any.whl
- Upload date:
- Size: 22.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.2 CPython/3.13.12 Darwin/25.3.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ebe7b6fcb1ff622dab77bef8ecacb16bcc689923c56edc8319bc8a8c57475bb0
|
|
| MD5 |
baf8bc4fae1a0a890e99ad5e6e5dddd4
|
|
| BLAKE2b-256 |
03e17be8aefed72650ed43a6b0fed5864cb596e65b2e80efcbf51d9e03bd8c9c
|