Skip to main content
Change of provenance

The repository or configuration that created this release differ from a previous release. View details.

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",
        ]

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

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

Change of provenance

The repository or configuration that created these release files differ from that of a previous release.

We recommend inspecting the repository and configuration before proceeding. View details.

Source distribution (sdist)

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

Built distribution (wheel)

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

Total release size: 26.8 kB

Release files / djangospice_api-0.3.0.tar.gz

Change of provenance

This file belongs to a release with changed provenance: the repository or configuration that created the release files differ from that of a previous release.

We recommend inspecting the repository and configuration before proceeding. View details.

Download URL djangospice_api-0.3.0.tar.gz
Size 12.2 kB
Tags Source
SHA-256 checksum
How to use checksums
4319f72c2b6c2a136f6292559c446aaa23bbc231adb9aec2190d0dd55d72e766
BLAKE2b-256 checksum
How to use checksums
72da7245af2667d6f7b69d89c055caa1184e5f82790f7d2ab15748be6423ccee
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 8, 2026.

Transparency log

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

Change of provenance

This file belongs to a release with changed provenance: the repository or configuration that created the release files differ from that of a previous release.

We recommend inspecting the repository and configuration before proceeding. View details.

Download URL djangospice_api-0.3.0-py3-none-any.whl
Size 14.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
da57d54a6cb0f57449766c000426ef8b14955262143f3a318862eb7079a2e2e1
BLAKE2b-256 checksum
How to use checksums
5f1adc74f1fef03a2c7039298ba64dbdb6cda87b9aa73100c6933d6c4ada01b6
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 8, 2026.

Transparency log

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

Change of provenance

The repository and configuration that created this release differ from a previous release.

While this could reflect a routine change by the project maintainers, it may also indicate that the release files have been compromised.

Select from 2 files

Attestation for djangospice_api-0.3.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 8, 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