Skip to main content

Automagically create a REST API for your Django models

Project description

Django Headless

PyPI version Python versions Django versions License

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 @expose 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

🚀 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 articles
  • POST /api/blog.article/ - Create new article
  • GET /api/blog.article/{id}/ - Retrieve specific article
  • PUT /api/blog.article/{id}/ - Update article
  • PATCH /api/blog.article/{id}/ - Partially update article
  • DELETE /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 configuration
  • PUT /api/config.siteconfiguration/ - Update configuration
  • PATCH /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:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Add tests for your changes
  5. Run the test suite (python manage.py test)
  6. Commit your changes (git commit -m 'Add amazing feature')
  7. Push to the branch (git push origin feature/amazing-feature)
  8. 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

📄 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_headless-1.0.0rc1.post1.tar.gz (17.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_headless-1.0.0rc1.post1-py3-none-any.whl (22.1 kB view details)

Uploaded Python 3

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

Hashes for django_headless-1.0.0rc1.post1.tar.gz
Algorithm Hash digest
SHA256 d8ffbca4b101ad4eb4737592e3b33bba2d284617327cc6b8255d8261c0013db2
MD5 f383148915b693e50da1442fbf708b4f
BLAKE2b-256 e9ec2612d800cc101ebcc3a945f2d1e2a41bd03f6115485d1771e15a1b886572

See more details on using hashes here.

File details

Details for the file django_headless-1.0.0rc1.post1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_headless-1.0.0rc1.post1-py3-none-any.whl
Algorithm Hash digest
SHA256 ebe7b6fcb1ff622dab77bef8ecacb16bcc689923c56edc8319bc8a8c57475bb0
MD5 baf8bc4fae1a0a890e99ad5e6e5dddd4
BLAKE2b-256 03e17be8aefed72650ed43a6b0fed5864cb596e65b2e80efcbf51d9e03bd8c9c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page