diff --git a/drf_spectacular/openapi.py b/drf_spectacular/openapi.py index ed00a828..534a5299 100644 --- a/drf_spectacular/openapi.py +++ b/drf_spectacular/openapi.py @@ -699,7 +699,10 @@ def _map_serializer_field(self, field, direction, bypass_extensions=False): # read_only fields do not have a Manager by design. go around and get field # from parent. also avoid calling Manager. __bool__ as it might be customized # to hit the database. - if getattr(field, 'queryset', None) is not None: + if not is_slug and getattr(field, 'pk_field') is not None: + schema = self._map_serializer_field(field.pk_field, direction) + return append_meta(schema, meta) + elif getattr(field, 'queryset', None) is not None: if is_slug: model = field.queryset.model source = [field.slug_field] @@ -718,7 +721,7 @@ def _map_serializer_field(self, field, direction, bypass_extensions=False): f'Could not derive type for under-specified {field.__class__.__name__} ' f'"{field.field_name}". The serializer has no associated model (Meta class) ' f'and this particular field has no type without a model association. Consider ' - f'changing the field or adding a Meta class. defaulting to string.' + f'changing the field or adding a Meta class. Defaulting to string.' ) return append_meta(build_basic_type(OpenApiTypes.STR), meta) diff --git a/tests/test_regressions.py b/tests/test_regressions.py index 0dd53299..eb7f3457 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -3444,3 +3444,20 @@ class XViewset(viewsets.ModelViewSet): 'readOnly': True } } + + +def test_primary_key_related_field_with_custom_pk_field(no_warnings): + class XSerializer(serializers.Serializer): + field = serializers.PrimaryKeyRelatedField( + read_only=True, + pk_field=serializers.IntegerField(), + ) + + class XViewset(viewsets.ModelViewSet): + serializer_class = XSerializer + queryset = SimpleModel.objects.all() + + schema = generate_schema('/x', XViewset) + assert schema['components']['schemas']['X']['properties']['field'] == { + 'readOnly': True, 'type': 'integer' + }