Propagate nullability in ModelSerializer (#8116)

Propagate the nullability of underlying model fields in ModelSerializer
when those fields are marked as read only. This ensures the correct
generation of OpenAPI schemas.

Fix #8041.
This commit is contained in:
Nikhil Benesch 2021-08-06 05:10:58 -04:00 committed by GitHub
parent 98e56e0327
commit b215375125
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 3 deletions

View File

@ -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)

View File

@ -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):