Djangospice API
Reusable API utilities for Django and Django REST Framework.
Djangospice API provides reusable serializers, API routing utilities, permissions, and common ViewSet functionality for building consistent and modular Django REST APIs.
Features
- Automatic API router discovery
- Modular application-level API routers
- Central API routing
- Automatic model-based ViewSet registration
- OpenAPI/Swagger tags
- Default API model permissions
- Action-aware serializers
- Nested relationship serialization
- Relationship ID and nested writes
- Generic related-object serialization
- Standard option serializers
- Bulk deletion support
Requirements
- Python 3.12+
- Django 5.0+
- Django REST Framework 3.15+
Installation
pip install djangospice-api
Configuration
Add the package to your Django project:
INSTALLED_APPS = [
# ...
"djangospice_api",
]
Include the API URLs:
from django.urls import include, path
urlpatterns = [
path("api/", include("djangospice_api.urls")),
]
Once configured, Djangospice API can discover API routers provided by installed applications automatically.
API Routers
Applications can expose their API endpoints through:
<application>/api/router.py
For example:
courses/
└── api/
└── router.py
The router can be a standard Django REST Framework router:
from rest_framework.routers import DefaultRouter
from .views import CourseViewSet
router = DefaultRouter()
router.register(
"courses",
CourseViewSet,
basename="course",
)
The application's routes are automatically included in the project's API.
For example:
/api/courses/
/api/courses/{id}/
Applications do not need to depend on the Djangospice runtime to define their routers.
APIRouter
Djangospice API provides APIRouter for applications that need additional routing functionality.
from djangospice_api.router import APIRouter
It supports:
- model-based registration
- automatic ViewSet registration
- router composition
- default API permissions
- OpenAPI tags
A shared router instance is also provided:
from djangospice_api.router import router
Registering a Model ViewSet
A ViewSet can be registered using an application label and model name:
router.register_model(
"students",
"student",
StudentViewSet,
)
A custom basename can be provided:
router.register_model(
"students",
"student",
StudentViewSet,
basename="students",
)
Automatic ViewSet Registration
For conventional ModelViewSets, the model can be detected from the ViewSet's queryset:
router.register_viewset(
StudentViewSet,
)
For example:
class StudentViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
The API router derives the application and model information automatically.
API Permissions
Djangospice API provides a default model-based permission system.
When a ViewSet does not define its own permission classes, the API router can apply:
ApiModelPermissions
Custom permissions can be supplied during registration:
router.register_viewset(
StudentViewSet,
permission_classes=[
IsAuthenticated,
],
)
Explicit permissions defined by a ViewSet are preserved unless registration specifies an override.
OpenAPI Documentation
When ViewSets are registered automatically, Djangospice API can provide OpenAPI tags for generated API documentation.
For example, application-based registration can produce tags such as:
Students
Courses
Billing
Custom tags can also be supplied:
router.register_viewset(
StudentViewSet,
swagger_tags=[
"Academic",
"Students",
],
)
This integrates with drf-spectacular.
BaseModelSerializer
BaseModelSerializer extends Django REST Framework's ModelSerializer with action-specific representations.
from djangospice_api.serializers import BaseModelSerializer
Example:
class CourseSerializer(BaseModelSerializer):
class Meta:
model = Course
fields = [
"id",
"code",
"name",
"department",
"description",
]
list_fields = [
"id",
"code",
"name",
"department",
]
detail_fields = [
"id",
"code",
"name",
"department",
"description",
]
Different field configurations can be provided for:
- list
- detail
- create
- update
- partial update
When an action-specific configuration is not supplied, the standard fields configuration is used.
Flattening Relationships
Relationships can be represented as human-readable values in list responses.
class CourseSerializer(BaseModelSerializer):
class Meta:
model = Course
fields = [
"id",
"code",
"name",
"department",
]
flatten_fields = [
"department",
]
A list response can then represent the department using its string representation rather than only its primary key.
This is useful for:
- data tables
- administrative interfaces
- lookup interfaces
- HTMX applications
- JavaScript clients
Hidden List Fields
Fields can be excluded from list responses:
class Meta:
model = Course
fields = [
"id",
"code",
"name",
"description",
"created_at",
]
hidden_fields = [
"description",
"created_at",
]
The fields remain available to other serializer actions.
GenericObjectRelatedField
GenericObjectRelatedField provides a generic representation of related objects.
from djangospice_api.serializers import GenericObjectRelatedField
A related object is represented using:
{
"id": 42,
"model_type": "Course",
"display_name": "Database Systems"
}
This is useful when an API works with generic or polymorphic relationships.
NestedModelSerializer
NestedModelSerializer extends BaseModelSerializer with support for Django model relationships.
from djangospice_api.serializers import NestedModelSerializer
It supports:
- ForeignKey
- OneToOneField
- ManyToManyField
Nested serializers can be discovered using conventional serializer names or explicitly configured.
Example:
class CourseSerializer(NestedModelSerializer):
class Meta:
model = Course
fields = [
"id",
"code",
"name",
"department",
]
Nested Serializer Configuration
Nested serializers can be explicitly specified:
class CourseSerializer(NestedModelSerializer):
class Meta:
model = Course
fields = [
"id",
"code",
"name",
"department",
]
serializers = {
"department": DepartmentSerializer,
}
This is useful when a model has multiple possible serializers.
Relationship Writes
Djangospice API provides consistent conventions for relationship writes.
| Relationship | Write field |
|---|---|
| ForeignKey | field_id |
| OneToOne | field_id |
| ManyToMany | field_ids |
| Nested ForeignKey | field_nested |
| Nested OneToOne | field_nested |
| Nested ManyToMany | field_nested |
For example:
{
"name": "Advanced Databases",
"prerequisites_ids": [
10,
11,
12
]
}
Nested relationships can also be supplied:
{
"name": "Advanced Databases",
"prerequisites_nested": [
{
"id": 10
},
{
"name": "Data Structures"
}
]
}
OptionModelSerializer
OptionModelSerializer provides a standard serializer for option and reference models.
from djangospice_api.serializers import OptionModelSerializer
The standard fields are:
id
name
value
slug
code
description
is_visible
Example:
class StatusSerializer(OptionModelSerializer):
class Meta:
model = Status
This is useful for:
- dropdown options
- lookup values
- status definitions
- configuration data
- reference data
BulkDeleteMixin
BulkDeleteMixin adds bulk deletion support to Django REST Framework ViewSets.
from djangospice_api.mixins import BulkDeleteMixin
Example:
class CourseViewSet(
BulkDeleteMixin,
ModelViewSet,
):
queryset = Course.objects.all()
serializer_class = CourseSerializer
The ViewSet provides:
POST /courses/bulk-delete/
Request:
{
"ids": [
1,
2,
3
]
}
Response:
{
"deleted": 3
}
Example
A typical Django application can combine the utilities:
from rest_framework.routers import DefaultRouter
from rest_framework.viewsets import ModelViewSet
from djangospice_api.mixins import BulkDeleteMixin
from .models import Course
from .serializers import CourseSerializer
class CourseViewSet(
BulkDeleteMixin,
ModelViewSet,
):
queryset = Course.objects.all()
serializer_class = CourseSerializer
router = DefaultRouter()
router.register(
"courses",
CourseViewSet,
basename="course",
)
Place the router in:
courses/api/router.py
and it will be discovered automatically.
Development
Clone the repository:
git clone https://github.com/briansimpo/djangospice_api.git
cd djangospice_api
Create a virtual environment:
python -m venv .venv
Activate the environment and install the package:
pip install -e .
License
This package is licensed under the MIT License.
See LICENSE for the full license text.
Metadata
Release files for djangospice-api 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| djangospice_api-0.2.0.tar.gz | 12.2 kB | With provenance | Details for djangospice_api-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| djangospice_api-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for djangospice_api-0.2.0-py3-none-any.whl |
Total release size: 26.8 kB
Release files / djangospice_api-0.2.0.tar.gz
| Download URL | djangospice_api-0.2.0.tar.gz |
|---|---|
| Size | 12.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
280dd26dfd0aa904125603c1e5aab944ca2985206c14c13e92d1c449b7d9fb6a
|
|
BLAKE2b-256 checksum How to use checksums |
9b7e1369b374d0e56fba57861d307bbf2167acdb12369352821ebc8a443ae818
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.
Transparency logRelease files / djangospice_api-0.2.0-py3-none-any.whl
| Download URL | djangospice_api-0.2.0-py3-none-any.whl |
|---|---|
| Size | 14.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a4db7ceb9394e7eec66fb502592ff947276a59ee4327bfe2f9d77e8177a1111d
|
|
BLAKE2b-256 checksum How to use checksums |
ea6b4f52ec52ae53f049f149ac09290363c0be05e2bdeb520499053525413072
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.
Transparency logSecurity for djangospice-api 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for djangospice_api-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.