diff --git a/drf_spectacular/openapi.py b/drf_spectacular/openapi.py index 6593dadc..4098a941 100644 --- a/drf_spectacular/openapi.py +++ b/drf_spectacular/openapi.py @@ -766,9 +766,10 @@ def _get_serializer_field_meta(self, field): if field.allow_null: meta['nullable'] = True if field.default is not None and field.default != empty and not callable(field.default): - if isinstance(field, serializers.ModelField): - # Skip coercion for lack of a better solution. ModelField.to_representation() is special - # in that it requires a model instance (which we don't have) instead of a plain value. + if isinstance(field, (serializers.ModelField, serializers.SerializerMethodField)): + # Skip coercion for lack of a better solution. ModelField.to_representation() + # and SerializerMethodField.to_representation() are special in that they require + # a model instance or object (which we don't have) instead of a plain value. default = field.default else: default = field.to_representation(field.default) diff --git a/tests/test_regressions.py b/tests/test_regressions.py index 7b821739..30249e61 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -2240,7 +2240,7 @@ def view_func(request, format=None): } -def test_serializer_modelfield_with_default_value(no_warnings): +def test_serializer_modelfield_and_methodfield_with_default_value(no_warnings): class M8Model(models.Model): field = models.IntegerField() @@ -2249,6 +2249,10 @@ class XSerializer(serializers.ModelSerializer): model_field=M8Model()._meta.get_field('field'), default=3 ) + field_smf = serializers.SerializerMethodField(default=4) + + def get_field_smf(self, obj) -> int: + return 0 # pragma: no cover class Meta: model = M8Model @@ -2262,6 +2266,9 @@ class XViewset(viewsets.ModelViewSet): assert schema['components']['schemas']['X']['properties']['field'] == { 'type': 'integer', 'default': 3 } + assert schema['components']['schemas']['X']['properties']['field_smf'] == { + 'type': 'integer', 'readOnly': True, 'default': 4 + } def test_literal_dot_in_regex_path(no_warnings):