mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-10-22 19:54:50 +03:00
Added validation on ManyToMany relations when default=None
+ Added tests
This commit is contained in:
parent
f0ba887761
commit
7e8962c622
|
@ -1090,6 +1090,14 @@ class ModelSerializer(Serializer):
|
|||
# Determine the fields that should be included on the serializer.
|
||||
fields = {}
|
||||
|
||||
# If it's a ManyToMany field, and the default is None, then raises an exception to prevent exceptions on .set()
|
||||
for field_name in declared_fields.keys():
|
||||
if field_name in info.relations and info.relations[field_name].to_many and declared_fields[field_name].default is None:
|
||||
raise ValueError(
|
||||
f"The field '{field_name}' on serializer '{self.__class__.__name__}' is a ManyToMany field and cannot have a default value of None. "
|
||||
"Please set an appropriate default value, such as an empty list, or remove the default."
|
||||
)
|
||||
|
||||
for field_name in field_names:
|
||||
# If the field is explicitly declared on the class then use that.
|
||||
if field_name in declared_fields:
|
||||
|
|
|
@ -6,12 +6,14 @@ from collections.abc import Mapping
|
|||
|
||||
import pytest
|
||||
from django.db import models
|
||||
from django.test import TestCase
|
||||
|
||||
from rest_framework import exceptions, fields, relations, serializers
|
||||
from rest_framework.fields import Field
|
||||
|
||||
from .models import (
|
||||
ForeignKeyTarget, NestedForeignKeySource, NullableForeignKeySource
|
||||
ForeignKeyTarget, ManyToManySource, ManyToManyTarget,
|
||||
NestedForeignKeySource, NullableForeignKeySource
|
||||
)
|
||||
from .utils import MockObject
|
||||
|
||||
|
@ -64,6 +66,7 @@ class TestSerializer:
|
|||
class ExampleSerializer(serializers.Serializer):
|
||||
char = serializers.CharField()
|
||||
integer = serializers.IntegerField()
|
||||
|
||||
self.Serializer = ExampleSerializer
|
||||
|
||||
def test_valid_serializer(self):
|
||||
|
@ -774,3 +777,35 @@ class TestSetValueMethod:
|
|||
ret = {'a': 1}
|
||||
self.s.set_value(ret, ['x', 'y'], 2)
|
||||
assert ret == {'a': 1, 'x': {'y': 2}}
|
||||
|
||||
|
||||
class TestWarningManyToMany(TestCase):
|
||||
def test_warning_many_to_many(self):
|
||||
"""Tests that using a PrimaryKeyRelatedField for a ManyToMany field breaks with default=None."""
|
||||
class ManyToManySourceSerializer(serializers.ModelSerializer):
|
||||
targets = serializers.PrimaryKeyRelatedField(
|
||||
many=True,
|
||||
queryset=ManyToManyTarget.objects.all(),
|
||||
default=None
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = ManyToManySource
|
||||
fields = '__all__'
|
||||
|
||||
# Instantiates with invalid data (not value for a ManyToMany field to force using the default)
|
||||
serializer = ManyToManySourceSerializer(data={
|
||||
"name": "Invalid Example",
|
||||
})
|
||||
|
||||
error_msg = "The field 'targets' on serializer 'ManyToManySourceSerializer' is a ManyToMany field and cannot have a default value of None. Please set an appropriate default value, such as an empty list, or remove the default."
|
||||
|
||||
# Calls to get_fields() should raise a ValueError
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
serializer.get_fields()
|
||||
assert str(exc_info.value) == error_msg
|
||||
|
||||
# Calls to is_valid() should behave the same
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
serializer.is_valid(raise_exception=True)
|
||||
assert str(exc_info.value) == error_msg
|
||||
|
|
Loading…
Reference in New Issue
Block a user