diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py index 5e07e2a006..cdfac5044b 100644 --- a/django/core/serializers/python.py +++ b/django/core/serializers/python.py @@ -88,7 +88,7 @@ def Deserializer(object_list, **options): for d in object_list: # Look up the model and starting build a dict of data for it. Model = _get_model(d["model"]) - data = {Model._meta.pk.attname: Model._meta.pk.to_python(d["pk"])} + data = {Model._meta.pk.attname: Model._meta.pk.to_python(d.get("pk", None))} m2m_data = {} model_fields = Model._meta.get_all_field_names() diff --git a/docs/topics/serialization.txt b/docs/topics/serialization.txt index 25884fa874..82cb3ffe5b 100644 --- a/docs/topics/serialization.txt +++ b/docs/topics/serialization.txt @@ -117,6 +117,16 @@ object and any associated relationship data. Calling ``DeserializedObject.save()`` saves the object to the database. +.. note:: + + If the ``pk`` attribute in the serialized data doesn't exist or is + null, a new instance will be saved to the database. + +.. versionchanged:: 1.6 + +In previous versions of Django, the ``pk`` attribute had to be present +on the serialized data or a ``DeserializationError`` would be raised. + This ensures that deserializing is a non-destructive operation even if the data in your serialized representation doesn't match what's currently in the database. Usually, working with these ``DeserializedObject`` instances looks diff --git a/tests/modeltests/serializers/tests.py b/tests/modeltests/serializers/tests.py index e39f17b68a..34d0f5f1b1 100644 --- a/tests/modeltests/serializers/tests.py +++ b/tests/modeltests/serializers/tests.py @@ -255,7 +255,7 @@ class SerializersTestBase(object): for obj in deserial_objs: self.assertFalse(obj.object.id) obj.save() - self.assertEqual(Category.objects.all().count(), 4) + self.assertEqual(Category.objects.all().count(), 5) class SerializersTransactionTestBase(object): @@ -290,6 +290,9 @@ class XmlSerializerTestCase(SerializersTestBase, TestCase): Reference + + Non-fiction + """ @staticmethod @@ -351,7 +354,15 @@ class XmlSerializerTransactionTestCase(SerializersTransactionTestBase, Transacti class JsonSerializerTestCase(SerializersTestBase, TestCase): serializer_name = "json" - pkless_str = """[{"pk": null, "model": "serializers.category", "fields": {"name": "Reference"}}]""" + pkless_str = """[ + { + "pk": null, + "model": "serializers.category", + "fields": {"name": "Reference"} + }, { + "model": "serializers.category", + "fields": {"name": "Non-fiction"} + }]""" @staticmethod def _validate_output(serial_str): @@ -433,6 +444,9 @@ else: pkless_str = """- fields: name: Reference pk: null + model: serializers.category +- fields: + name: Non-fiction model: serializers.category""" @staticmethod