Fixed #32420 -- Fixed detecting primary key values in deserialization when PK is also a FK.
This commit is contained in:
parent
3f8979e37b
commit
8e90560aa8
|
@ -257,7 +257,7 @@ def build_instance(Model, data, db):
|
||||||
natural keys, try to retrieve it from the database.
|
natural keys, try to retrieve it from the database.
|
||||||
"""
|
"""
|
||||||
default_manager = Model._meta.default_manager
|
default_manager = Model._meta.default_manager
|
||||||
pk = data.get(Model._meta.pk.name)
|
pk = data.get(Model._meta.pk.attname)
|
||||||
if (pk is None and hasattr(default_manager, 'get_by_natural_key') and
|
if (pk is None and hasattr(default_manager, 'get_by_natural_key') and
|
||||||
hasattr(Model, 'natural_key')):
|
hasattr(Model, 'natural_key')):
|
||||||
natural_key = Model(**data).natural_key()
|
natural_key = Model(**data).natural_key()
|
||||||
|
|
|
@ -53,3 +53,17 @@ class NaturalPKWithDefault(models.Model):
|
||||||
|
|
||||||
def natural_key(self):
|
def natural_key(self):
|
||||||
return (self.name,)
|
return (self.name,)
|
||||||
|
|
||||||
|
|
||||||
|
class FKAsPKNoNaturalKeyManager(models.Manager):
|
||||||
|
def get_by_natural_key(self, *args, **kwargs):
|
||||||
|
return super().get_by_natural_key(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class FKAsPKNoNaturalKey(models.Model):
|
||||||
|
pk_fk = models.ForeignKey(NaturalKeyAnchor, on_delete=models.CASCADE, primary_key=True)
|
||||||
|
|
||||||
|
objects = FKAsPKNoNaturalKeyManager()
|
||||||
|
|
||||||
|
def natural_key(self):
|
||||||
|
raise NotImplementedError('This method was not expected to be called.')
|
||||||
|
|
|
@ -3,8 +3,8 @@ from django.db import connection
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Child, FKDataNaturalKey, NaturalKeyAnchor, NaturalKeyThing,
|
Child, FKAsPKNoNaturalKey, FKDataNaturalKey, NaturalKeyAnchor,
|
||||||
NaturalPKWithDefault,
|
NaturalKeyThing, NaturalPKWithDefault,
|
||||||
)
|
)
|
||||||
from .tests import register_tests
|
from .tests import register_tests
|
||||||
|
|
||||||
|
@ -200,6 +200,20 @@ def pk_with_default(self, format):
|
||||||
self.assertEqual(objs[0].object.pk, obj.pk)
|
self.assertEqual(objs[0].object.pk, obj.pk)
|
||||||
|
|
||||||
|
|
||||||
|
def fk_as_pk_natural_key_not_called(self, format):
|
||||||
|
"""
|
||||||
|
The deserializer doesn't rely on natural keys when a model has a custom
|
||||||
|
primary key that is a ForeignKey.
|
||||||
|
"""
|
||||||
|
o1 = NaturalKeyAnchor.objects.create(data='978-1590599969')
|
||||||
|
o2 = FKAsPKNoNaturalKey.objects.create(pk_fk=o1)
|
||||||
|
serialized_data = serializers.serialize(format, [o1, o2])
|
||||||
|
deserialized_objects = list(serializers.deserialize(format, serialized_data))
|
||||||
|
self.assertEqual(len(deserialized_objects), 2)
|
||||||
|
for obj in deserialized_objects:
|
||||||
|
self.assertEqual(obj.object.pk, o1.pk)
|
||||||
|
|
||||||
|
|
||||||
# Dynamically register tests for each serializer
|
# Dynamically register tests for each serializer
|
||||||
register_tests(NaturalKeySerializerTests, 'test_%s_natural_key_serializer', natural_key_serializer_test)
|
register_tests(NaturalKeySerializerTests, 'test_%s_natural_key_serializer', natural_key_serializer_test)
|
||||||
register_tests(NaturalKeySerializerTests, 'test_%s_serializer_natural_keys', natural_key_test)
|
register_tests(NaturalKeySerializerTests, 'test_%s_serializer_natural_keys', natural_key_test)
|
||||||
|
@ -209,3 +223,8 @@ register_tests(NaturalKeySerializerTests, 'test_%s_forward_references_fk_errors'
|
||||||
register_tests(NaturalKeySerializerTests, 'test_%s_forward_references_m2ms', forward_ref_m2m_test)
|
register_tests(NaturalKeySerializerTests, 'test_%s_forward_references_m2ms', forward_ref_m2m_test)
|
||||||
register_tests(NaturalKeySerializerTests, 'test_%s_forward_references_m2m_errors', forward_ref_m2m_with_error_test)
|
register_tests(NaturalKeySerializerTests, 'test_%s_forward_references_m2m_errors', forward_ref_m2m_with_error_test)
|
||||||
register_tests(NaturalKeySerializerTests, 'test_%s_pk_with_default', pk_with_default)
|
register_tests(NaturalKeySerializerTests, 'test_%s_pk_with_default', pk_with_default)
|
||||||
|
register_tests(
|
||||||
|
NaturalKeySerializerTests,
|
||||||
|
'test_%s_fk_as_pk_natural_key_not_called',
|
||||||
|
fk_as_pk_natural_key_not_called,
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue