Fixed #28385 -- Fixed deserializing natural keys when primary key has a default value.
Co-Authored-By: Hasan Ramezani <hasan.r67@gmail.com>
This commit is contained in:
parent
926fa7116f
commit
dcd1025f4c
|
@ -256,15 +256,18 @@ def build_instance(Model, data, db):
|
||||||
If the model instance doesn't have a primary key and the model supports
|
If the model instance doesn't have a primary key and the model supports
|
||||||
natural keys, try to retrieve it from the database.
|
natural keys, try to retrieve it from the database.
|
||||||
"""
|
"""
|
||||||
obj = Model(**data)
|
default_manager = Model._meta.default_manager
|
||||||
if (obj.pk is None and hasattr(Model, 'natural_key') and
|
pk = data.get(Model._meta.pk.name)
|
||||||
hasattr(Model._default_manager, 'get_by_natural_key')):
|
if (pk is None and hasattr(default_manager, 'get_by_natural_key') and
|
||||||
natural_key = obj.natural_key()
|
hasattr(Model, 'natural_key')):
|
||||||
|
natural_key = Model(**data).natural_key()
|
||||||
try:
|
try:
|
||||||
obj.pk = Model._default_manager.db_manager(db).get_by_natural_key(*natural_key).pk
|
data[Model._meta.pk.attname] = Model._meta.pk.to_python(
|
||||||
|
default_manager.db_manager(db).get_by_natural_key(*natural_key).pk
|
||||||
|
)
|
||||||
except Model.DoesNotExist:
|
except Model.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
return obj
|
return Model(**data)
|
||||||
|
|
||||||
|
|
||||||
def deserialize_m2m_values(field, field_value, using, handle_forward_references):
|
def deserialize_m2m_values(field, field_value, using, handle_forward_references):
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
"""Models for test_natural.py"""
|
"""Models for test_natural.py"""
|
||||||
|
import uuid
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,3 +39,17 @@ class NaturalKeyThing(models.Model):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.key
|
return self.key
|
||||||
|
|
||||||
|
|
||||||
|
class NaturalPKWithDefault(models.Model):
|
||||||
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||||
|
name = models.CharField(max_length=100, unique=True)
|
||||||
|
|
||||||
|
class Manager(models.Manager):
|
||||||
|
def get_by_natural_key(self, name):
|
||||||
|
return self.get(name=name)
|
||||||
|
|
||||||
|
objects = Manager()
|
||||||
|
|
||||||
|
def natural_key(self):
|
||||||
|
return (self.name,)
|
||||||
|
|
|
@ -2,7 +2,10 @@ from django.core import serializers
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from .models import Child, FKDataNaturalKey, NaturalKeyAnchor, NaturalKeyThing
|
from .models import (
|
||||||
|
Child, FKDataNaturalKey, NaturalKeyAnchor, NaturalKeyThing,
|
||||||
|
NaturalPKWithDefault,
|
||||||
|
)
|
||||||
from .tests import register_tests
|
from .tests import register_tests
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,6 +185,21 @@ def forward_ref_m2m_with_error_test(self, format):
|
||||||
obj.save_deferred_fields()
|
obj.save_deferred_fields()
|
||||||
|
|
||||||
|
|
||||||
|
def pk_with_default(self, format):
|
||||||
|
"""
|
||||||
|
The deserializer works with natural keys when the primary key has a default
|
||||||
|
value.
|
||||||
|
"""
|
||||||
|
obj = NaturalPKWithDefault.objects.create(name='name')
|
||||||
|
string_data = serializers.serialize(
|
||||||
|
format, NaturalPKWithDefault.objects.all(), use_natural_foreign_keys=True,
|
||||||
|
use_natural_primary_keys=True,
|
||||||
|
)
|
||||||
|
objs = list(serializers.deserialize(format, string_data))
|
||||||
|
self.assertEqual(len(objs), 1)
|
||||||
|
self.assertEqual(objs[0].object.pk, obj.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)
|
||||||
|
@ -190,3 +208,4 @@ register_tests(NaturalKeySerializerTests, 'test_%s_forward_references_fks', forw
|
||||||
register_tests(NaturalKeySerializerTests, 'test_%s_forward_references_fk_errors', forward_ref_fk_with_error_test)
|
register_tests(NaturalKeySerializerTests, 'test_%s_forward_references_fk_errors', forward_ref_fk_with_error_test)
|
||||||
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)
|
||||||
|
|
Loading…
Reference in New Issue