diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 49eec8259..9ea57f1af 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -1326,9 +1326,8 @@ class ModelSerializer(Serializer): """ if extra_kwargs.get('read_only', False): for attr in [ - 'required', 'default', 'allow_blank', 'allow_null', - 'min_length', 'max_length', 'min_value', 'max_value', - 'validators', 'queryset' + 'required', 'default', 'allow_blank', 'min_length', + 'max_length', 'min_value', 'max_value', 'validators', 'queryset' ]: kwargs.pop(attr, None) diff --git a/tests/schemas/test_openapi.py b/tests/schemas/test_openapi.py index aef20670e..daa035a3f 100644 --- a/tests/schemas/test_openapi.py +++ b/tests/schemas/test_openapi.py @@ -2,6 +2,7 @@ import uuid import warnings import pytest +from django.db import models from django.test import RequestFactory, TestCase, override_settings from django.urls import path from django.utils.translation import gettext_lazy as _ @@ -110,6 +111,24 @@ class TestFieldMapping(TestCase): assert data['properties']['default_false']['default'] is False, "default must be false" assert 'default' not in data['properties']['without_default'], "default must not be defined" + def test_nullable_fields(self): + class Model(models.Model): + rw_field = models.CharField(null=True) + ro_field = models.CharField(null=True) + + class Serializer(serializers.ModelSerializer): + class Meta: + model = Model + fields = ["rw_field", "ro_field"] + read_only_fields = ["ro_field"] + + inspector = AutoSchema() + + data = inspector.map_serializer(Serializer()) + assert data['properties']['rw_field']['nullable'], "rw_field nullable must be true" + assert data['properties']['ro_field']['nullable'], "ro_field nullable must be true" + assert data['properties']['ro_field']['readOnly'], "ro_field read_only must be true" + @pytest.mark.skipif(uritemplate is None, reason='uritemplate not installed.') class TestOperationIntrospection(TestCase):