diff options
| author | Youngkwang Yang <me@youngkwang.dev> | 2025-12-18 13:49:13 +0900 |
|---|---|---|
| committer | Jacob Walls <jacobtylerwalls@gmail.com> | 2025-12-22 14:21:01 -0500 |
| commit | 95394443bff2cd6c5cb47c752422fe1f391bb43d (patch) | |
| tree | 9569a6075cf7152be47c5163c952fb76c8ce58ac /tests | |
| parent | 6ee8e9d56c17eb0014e73189950a9e8de2a8ec0e (diff) | |
Fixed #36786 -- Fixed XML serialization of None values in natural keys.
None values in natural keys were incorrectly serialized as the string
"None", causing deserialization to fail for fields like UUIDField.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/serializers/models/natural.py | 28 | ||||
| -rw-r--r-- | tests/serializers/test_natural.py | 66 |
2 files changed, 94 insertions, 0 deletions
diff --git a/tests/serializers/models/natural.py b/tests/serializers/models/natural.py index f32d781a76..3b01385e8f 100644 --- a/tests/serializers/models/natural.py +++ b/tests/serializers/models/natural.py @@ -91,3 +91,31 @@ class PostToOptOutSubclassUser(models.Model): subscribers = models.ManyToManyField( SubclassNaturalKeyOptOutUser, related_name="subscribed_posts", blank=True ) + + +class NaturalKeyWithNullableFieldManager(models.Manager): + def get_by_natural_key(self, name, optional_id): + return self.get(name=name, optional_id=optional_id) + + +class NaturalKeyWithNullableField(models.Model): + name = models.CharField(max_length=100) + optional_id = models.CharField(max_length=100, null=True, blank=True) + + objects = NaturalKeyWithNullableFieldManager() + + class Meta: + unique_together = [["name", "optional_id"]] + + def natural_key(self): + return (self.name, self.optional_id) + + +class FKToNaturalKeyWithNullable(models.Model): + ref = models.ForeignKey( + NaturalKeyWithNullableField, on_delete=models.CASCADE, null=True + ) + refs = models.ManyToManyField( + NaturalKeyWithNullableField, related_name="m2m_referrers" + ) + data = models.CharField(max_length=100, default="") diff --git a/tests/serializers/test_natural.py b/tests/serializers/test_natural.py index 322abeb7fc..e5592f97c8 100644 --- a/tests/serializers/test_natural.py +++ b/tests/serializers/test_natural.py @@ -6,8 +6,10 @@ from .models import ( Child, FKAsPKNoNaturalKey, FKDataNaturalKey, + FKToNaturalKeyWithNullable, NaturalKeyAnchor, NaturalKeyThing, + NaturalKeyWithNullableField, NaturalPKWithDefault, PostToOptOutSubclassUser, SubclassNaturalKeyOptOutUser, @@ -280,6 +282,60 @@ def natural_key_opt_out_test(self, format): ) +def nullable_natural_key_fk_test(self, format): + target_with_none = NaturalKeyWithNullableField.objects.create( + name="test_none", + optional_id=None, + ) + target_with_value = NaturalKeyWithNullableField.objects.create( + name="test_value", + optional_id="some_id", + ) + fk_to_none = FKToNaturalKeyWithNullable.objects.create( + ref=target_with_none, + data="points_to_none", + ) + fk_to_value = FKToNaturalKeyWithNullable.objects.create( + ref=target_with_value, + data="points_to_value", + ) + objects = [target_with_none, target_with_value, fk_to_none, fk_to_value] + serialized = serializers.serialize( + format, + objects, + use_natural_foreign_keys=True, + use_natural_primary_keys=True, + ) + objs = list(serializers.deserialize(format, serialized)) + self.assertEqual(objs[2].object.ref_id, target_with_none.pk) + self.assertEqual(objs[3].object.ref_id, target_with_value.pk) + + +def nullable_natural_key_m2m_test(self, format): + target_with_none = NaturalKeyWithNullableField.objects.create( + name="test_none", + optional_id=None, + ) + target_with_value = NaturalKeyWithNullableField.objects.create( + name="test_value", + optional_id="some_id", + ) + m2m_obj = FKToNaturalKeyWithNullable.objects.create(data="m2m_test") + m2m_obj.refs.set([target_with_none, target_with_value]) + objects = [target_with_none, target_with_value, m2m_obj] + serialized = serializers.serialize( + format, + objects, + use_natural_foreign_keys=True, + use_natural_primary_keys=True, + ) + objs = list(serializers.deserialize(format, serialized)) + self.assertCountEqual( + objs[2].m2m_data["refs"], + [target_with_none.pk, target_with_value.pk], + ) + + # Dynamically register tests for each serializer register_tests( NaturalKeySerializerTests, @@ -319,3 +375,13 @@ register_tests( "test_%s_natural_key_opt_out", natural_key_opt_out_test, ) +register_tests( + NaturalKeySerializerTests, + "test_%s_nullable_natural_key_fk", + nullable_natural_key_fk_test, +) +register_tests( + NaturalKeySerializerTests, + "test_%s_nullable_natural_key_m2m", + nullable_natural_key_m2m_test, +) |
