Django REST Framework

Full integration with Django REST Framework views and serializers.

DisplayIDMixin

For ViewSets

When your model extends DisplayIDModel, the prefix is inherited automatically:

from rest_framework.viewsets import ModelViewSet
from django_display_ids.contrib.rest_framework import DisplayIDMixin

class InvoiceViewSet(DisplayIDMixin, ModelViewSet):
    queryset = Invoice.objects.all()
    serializer_class = InvoiceSerializer
    lookup_url_kwarg = "id"

For APIView

from rest_framework.views import APIView
from rest_framework.response import Response
from django_display_ids.contrib.rest_framework import DisplayIDMixin

class InvoiceView(DisplayIDMixin, APIView):
    lookup_url_kwarg = "id"

    def get_queryset(self):
        return Invoice.objects.all()

    def get(self, request, *args, **kwargs):
        invoice = self.get_object()
        return Response({"id": str(invoice.id)})

Configuration Attributes

lookup_url_kwarg

The URL parameter name. Defaults to "pk".

lookup_strategies

Tuple of strategies to try. Defaults to ("display_id", "uuid", "slug").

display_id_prefix

Expected prefix. When None (the default), auto-detected by resolve_object from the model’s display_id_prefix attribute.

uuid_field

UUID field name. When None (the default), auto-detected by resolve_object from the model’s uuid_field attribute, then the DISPLAY_IDS["UUID_FIELD"] setting, then "id".

slug_field

Slug field name. When None (the default), auto-detected by resolve_object from the model’s slug_field attribute, then the DISPLAY_IDS["SLUG_FIELD"] setting, then "slug".

Error Handling

  • ObjectNotFoundErrorNotFound (404)

  • InvalidIdentifierErrorParseError (400)

  • UnknownPrefixErrorParseError (400)

DisplayIDField

Include display IDs in your API responses:

from rest_framework import serializers
from django_display_ids.contrib.rest_framework import DisplayIDField

class InvoiceSerializer(serializers.Serializer):
    id = serializers.UUIDField(read_only=True)
    display_id = DisplayIDField()
    name = serializers.CharField()

# Output: {"id": "...", "display_id": "inv_2aUyqjCzEIiEcYMKj7TZtw", ...}

The field reads the prefix from the model’s display_id_prefix. Override it explicitly:

display_id = DisplayIDField(prefix="inv")

The prefix must be 1-16 lowercase letters. Invalid prefixes raise ValueError at initialization.

When to use prefix_from

Sometimes the row being serialized is a projection of another model — for example a database-view-backed report row that mirrors Invoice data but is not an Invoice instance and carries no display_id_prefix of its own. In that case, point the field at the source model rather than hardcoding its prefix string:

class InvoiceReportSerializer(serializers.ModelSerializer):
    # InvoiceReport is a view-backed projection of Invoice.
    display_id = DisplayIDField(prefix_from=Invoice)

    class Meta:
        model = InvoiceReport
        fields = ("display_id", "total", "issued_on")

prefix_from=Invoice reads Invoice.display_id_prefix dynamically — it is equivalent to prefix="inv" but stays in sync if the model’s prefix changes. prefix and prefix_from are mutually exclusive. If prefix_from points at a class with no display_id_prefix, a ValueError is raised at initialization (app startup), not on the first request.

Tolerating a missing prefix

By default the field raises ValueError when no prefix can be resolved for an instance. When a single serializer handles heterogeneous rows — only some of which carry a prefix — pass required=False to return None instead:

display_id = DisplayIDField(required=False)

Resolution precedence

The field resolves the prefix from (in order):

  1. Field’s prefix= argument

  2. Field’s prefix_from= model class

  3. The serialized instance’s display_id_prefix attribute

If none resolve, the field raises ValueError unless required=False was passed, in which case it returns None.

OpenAPI / drf-spectacular

When drf-spectacular is installed, DisplayIDField automatically generates proper schema with prefix-specific examples. No configuration needed.

The extension resolves the prefix from (in order):

  1. Field’s prefix= or prefix_from= argument

  2. Serializer’s Meta.model.display_id_prefix

  3. View’s queryset model

Path Parameter Descriptions

Use the provided helper for consistent API documentation:

from django_display_ids.contrib.drf_spectacular import id_param_description
from drf_spectacular.utils import extend_schema, OpenApiParameter
from drf_spectacular.types import OpenApiTypes

@extend_schema(
    parameters=[
        OpenApiParameter(
            "id",
            OpenApiTypes.STR,
            OpenApiParameter.PATH,
            description=id_param_description("inv"),
            # -> "Identifier: display_id (inv_xxx) or UUID"
        )
    ],
)
class InvoiceViewSet(DisplayIDMixin, ModelViewSet):
    ...

For endpoints that also accept slugs:

description=id_param_description("app", with_slug=True)
# -> "Identifier: display_id (app_xxx), UUID, or slug"

For display ID only (no UUID fallback):

description=id_param_description("inv", with_uuid=False)
# -> "Identifier: display_id (inv_xxx)"