In my Django project, I have this URL definition
router.register(
r"device-types/(?P<device_type_id>[\d\w-]+)/variants/(?P<variant_id>[\d\w-]+)/accessible-sub-paths",
AccessibleSubPathViewSet,
basename="accessible-sub-paths",
)
Note that the parameters are device_type_id
and variant_id
.
The referenced viewset is
class AccessibleSubPathViewSet(viewsets.ModelViewSet):
"""
API for accessible sub paths.
Permissions:
- [UserIsOperator,]
"""
serializer_class = AccessibleSubPathSerializer
permission_classes = (custompermissions.UserIsOperator,)
def get_queryset(self):
return AccessibleSubPath.objects.filter(variant=self.kwargs["variant_id"])
And the serializer is
class AccessibleSubPathSerializer(serializers.ModelSerializer):
class Meta:
model = models.AccessibleSubPath
fields = (
"id",
"schema_path",
)
read_only_fields = ("id",)
When I run spectacular
to generate the openapi spec, I get this warning
/code/django/devices/viewsets.py:146: Warning [AccessibleSubPathViewSet]: could not derive type of path parameter "id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. <int:id>) or annotating the parameter type with @extend_schema. Defaulting to "string".
But "id"
is not a path parameter—it's a serializer field.
How do I clear this warning?
The answer is that spectacular infers the /{id}
parameter for the retrieve operation in ModelViewSet
. Specifying the types using extend_schema
clears the warning, like this
@extend_schema(
parameters=[
OpenApiParameter(
name="device_type_id",
type=OpenApiTypes.UUID,
location=OpenApiParameter.PATH,
),
OpenApiParameter(
name="variant_id",
type=OpenApiTypes.UUID,
location=OpenApiParameter.PATH,
),
OpenApiParameter(
name="id",
type=OpenApiTypes.UUID,
location=OpenApiParameter.PATH,
),
],
)
class AccessibleSubPathViewSet(viewsets.ModelViewSet):
"""
API for accessible sub paths.
Permissions:
- [UserIsOperator,]
"""
serializer_class = AccessibleSubPathSerializer
permission_classes = (custompermissions.UserIsOperator,)
def get_queryset(self):
return AccessibleSubPath.objects.filter(variant=self.kwargs["variant_id"])