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_kwargThe URL parameter name. Defaults to
"pk".lookup_strategiesTuple of strategies to try. Defaults to
("display_id", "uuid", "slug").display_id_prefixExpected prefix. When
None(the default), auto-detected byresolve_objectfrom the model’sdisplay_id_prefixattribute.uuid_fieldUUID field name. When
None(the default), auto-detected byresolve_objectfrom the model’suuid_fieldattribute, then theDISPLAY_IDS["UUID_FIELD"]setting, then"id".slug_fieldSlug field name. When
None(the default), auto-detected byresolve_objectfrom the model’sslug_fieldattribute, then theDISPLAY_IDS["SLUG_FIELD"]setting, then"slug".
Error Handling¶
ObjectNotFoundError→NotFound(404)InvalidIdentifierError→ParseError(400)UnknownPrefixError→ParseError(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):
Field’s
prefix=argumentField’s
prefix_from=model classThe serialized instance’s
display_id_prefixattribute
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):
Field’s
prefix=orprefix_from=argumentSerializer’s
Meta.model.display_id_prefixView’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)"