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):
+
"""
@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