Merge pull request #841 from bckohan/drf_bug

Polymorphic serializer validated data is now updated with the child data
This commit is contained in:
Brian Kohan 2026-01-13 15:42:18 -08:00 committed by GitHub
commit 8b2cb37ae9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 79 additions and 4 deletions

View File

@ -1,7 +1,12 @@
Changelog
=========
v4.10.0 (2026-XX-XX)
v4.10.1 (2026-01-13)
--------------------
* Fixed `Django-polymorphic does not update the PolymorphicSerializer's validated_data after running the child's validation method <https://github.com/jazzband/django-polymorphic/pull/378>`_
v4.10.0 (2026-01-13)
--------------------
This release is primarily an integrations release. Many tests were added for the documented

View File

@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "django-polymorphic"
version = "4.10.0"
version = "4.10.1"
description = "Seamless polymorphic inheritance for Django models."
readme = "README.md"
license = "BSD-3-Clause"

View File

@ -19,7 +19,7 @@ r"""
Seamless Polymorphic Inheritance for Django Models
"""
VERSION = "4.10.0"
VERSION = "4.10.1"
__title__ = "Django Polymorphic"
__version__ = VERSION # version synonym for backwards compatibility

View File

@ -93,6 +93,10 @@ class PolymorphicSerializer(serializers.Serializer):
child_valid = False
else:
child_valid = serializer.is_valid(*args, **kwargs)
# Update parent's validated_data with child's validated_data
# to preserve any modifications made in child's validate() method
if child_valid and hasattr(self, "_validated_data"):
self._validated_data.update(serializer._validated_data)
self._errors.update(serializer.errors)
return valid and child_valid

View File

@ -3,6 +3,7 @@ from django.core.exceptions import ImproperlyConfigured
import pytest
try:
from rest_framework import serializers
from rest_framework.test import APIClient
from polymorphic.contrib.drf.serializers import PolymorphicSerializer
@ -302,6 +303,71 @@ class TestPolymorphicSerializer:
assert "resourcetype" in excinfo.value.detail
assert "Invalid resourcetype" in str(excinfo.value.detail["resourcetype"])
def test_validate_method_modifications_are_preserved(self):
"""Test that modifications made in child serializer's validate() method are preserved."""
# Track whether the extra_field was present during create
created_with_extra_field = []
# Create a custom serializer that adds a field in validate()
class CustomBlogOneSerializer(BlogOneSerializer):
extra_field = serializers.CharField(required=False, allow_null=True)
class Meta(BlogOneSerializer.Meta):
fields = BlogOneSerializer.Meta.fields + ("extra_field",)
def validate(self, attrs):
attrs = super().validate(attrs)
# Simulate adding data in validate(), like adding the current user
attrs["extra_field"] = "added_in_validate"
return attrs
def create(self, validated_data):
# Record whether extra_field was in validated_data
created_with_extra_field.append("extra_field" in validated_data)
# Remove extra_field before creating the model instance
validated_data.pop("extra_field", None)
return super().create(validated_data)
class CustomBlogPolymorphicSerializer(PolymorphicSerializer):
model_serializer_mapping = {
BlogBase: BlogBaseSerializer,
BlogOne: CustomBlogOneSerializer,
}
# Create data without the extra_field
data = {
"name": "test",
"slug": "test-slug",
"info": "test-info",
"resourcetype": "BlogOne",
}
serializer = CustomBlogPolymorphicSerializer(data=data)
assert serializer.is_valid(), f"Validation errors: {serializer.errors}"
# Verify that the extra_field added in validate() is in validated_data
assert "extra_field" in serializer.validated_data
assert serializer.validated_data["extra_field"] == "added_in_validate"
# Verify that resource_type field is still preserved in parent's validated_data
assert "resourcetype" in serializer.validated_data
assert serializer.validated_data["resourcetype"] == "BlogOne"
# Save and verify that the field was present during create
# Note: This would fail before the fix because the parent's _validated_data
# wasn't updated with the child's _validated_data after calling child.is_valid()
instance = serializer.save()
# Verify that extra_field was indeed present when create() was called
assert created_with_extra_field == [True], (
"extra_field should have been in validated_data when create() was called"
)
# Verify the instance was created successfully
assert instance.name == "test"
assert instance.slug == "test-slug"
assert instance.info == "test-info"
class TestProjectViewSet:
"""Test the example Project ViewSet with polymorphic serializers."""

View File

@ -654,7 +654,7 @@ wheels = [
[[package]]
name = "django-polymorphic"
version = "4.10.0"
version = "4.10.1"
source = { editable = "." }
dependencies = [
{ name = "django", version = "5.2.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" },