diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 163abf4f0..44e4b04b1 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -896,7 +896,10 @@ class ModelSerializer(Serializer): # Update an existing instance... if instance is not None: for key, val in attrs.items(): - setattr(instance, key, val) + try: + setattr(instance, key, val) + except ValueError: + self._errors[key] = self.error_messages['required'] # ...or create a new instance else: diff --git a/rest_framework/tests/test_serializer.py b/rest_framework/tests/test_serializer.py index 1f85a4749..eca467ee2 100644 --- a/rest_framework/tests/test_serializer.py +++ b/rest_framework/tests/test_serializer.py @@ -558,6 +558,29 @@ class ModelValidationTests(TestCase): self.assertFalse(second_serializer.is_valid()) self.assertEqual(second_serializer.errors, {'title': ['Album with this Title already exists.']}) + def test_foreign_key_is_null_with_partial(self): + """ + Test ModelSerializer validation with partial=True + + Specifically test that a null foreign key does not pass validation + """ + album = Album(title='test') + album.save() + + class PhotoSerializer(serializers.ModelSerializer): + class Meta: + model = Photo + + photo_serializer = PhotoSerializer(data={'description': 'test', 'album': album.pk}) + self.assertTrue(photo_serializer.is_valid()) + photo = photo_serializer.save() + + # Updating only the album (foreign key) + photo_serializer = PhotoSerializer(instance=photo, data={'album': ''}, partial=True) + self.assertFalse(photo_serializer.is_valid()) + self.assertTrue('album' in photo_serializer.errors) + self.assertEqual(photo_serializer.errors['album'], photo_serializer.error_messages['required']) + def test_foreign_key_with_partial(self): """ Test ModelSerializer validation with partial=True