Skip to main content

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

djangospice-api is licensed under the MIT License.

See LICENSE for the full license text.


Project

Djangospice API on GitHub

Metadata

Release files for djangospice-api 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for djangospice-api 0.1.0
File Size Uploaded Provenance Actions
djangospice_api-0.1.0.tar.gz 12.2 kB With provenance Details for djangospice_api-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for djangospice-api 0.1.0
File Interpreter ABI Platform Actions
djangospice_api-0.1.0-py3-none-any.whl Python 3 none any Details for djangospice_api-0.1.0-py3-none-any.whl

Total release size: 26.9 kB

Release files / djangospice_api-0.1.0.tar.gz

Download URL djangospice_api-0.1.0.tar.gz
Size 12.2 kB
Tags Source
SHA-256 checksum
How to use checksums
a5b6ede18f4b4a75bf5439520fa5cd9159edf1591d7106fe5f4ab778e073834d
BLAKE2b-256 checksum
How to use checksums
5e9f71ce1631ec2b2e0000f2e4bed501c8f1c3031bebe490b1abb3501f39c228
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 log

Release files / djangospice_api-0.1.0-py3-none-any.whl

Download URL djangospice_api-0.1.0-py3-none-any.whl
Size 14.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f976b9bbab411bad9b9d5ff7422d03d9a9f7ccba66c2c09ab56f5f831306e76c
BLAKE2b-256 checksum
How to use checksums
86c73add6aa914eecd77cd7ecb105410a5bfe1e6594a8f4d762586b078e5fe0b
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 log

Security for djangospice-api 0.1.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.

Select from 2 files

Attestation for djangospice_api-0.1.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 log

A 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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page