diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py
index 3defb6aa27..a68ea21f78 100644
--- a/django/core/serializers/python.py
+++ b/django/core/serializers/python.py
@@ -111,6 +111,10 @@ def Deserializer(object_list, **options):
if hasattr(field_value, '__iter__'):
obj = field.rel.to._default_manager.db_manager(db).get_by_natural_key(*field_value)
value = getattr(obj, field.rel.field_name)
+ # If this is a natural foreign key to an object that
+ # has a FK/O2O as the foreign key, use the FK value
+ if field.rel.to._meta.pk.rel:
+ value = value.pk
else:
value = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
data[field.attname] = value
diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py
index b0d8d49397..5fef3b6936 100644
--- a/django/core/serializers/xml_serializer.py
+++ b/django/core/serializers/xml_serializer.py
@@ -221,6 +221,10 @@ class Deserializer(base.Deserializer):
field_value = [getInnerText(k).strip() for k in keys]
obj = field.rel.to._default_manager.db_manager(self.db).get_by_natural_key(*field_value)
obj_pk = getattr(obj, field.rel.field_name)
+ # If this is a natural foreign key to an object that
+ # has a FK/O2O as the foreign key, use the FK value
+ if field.rel.to._meta.pk.rel:
+ obj_pk = obj_pk.pk
else:
# Otherwise, treat like a normal PK
field_value = getInnerText(node).strip()
diff --git a/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance.json b/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance.json
new file mode 100644
index 0000000000..08e5d4feee
--- /dev/null
+++ b/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance.json
@@ -0,0 +1,18 @@
+[
+ {
+ "pk": 1,
+ "model": "fixtures_regress.nkchild",
+ "fields": {
+ "data": "apple"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "fixtures_regress.reftonkchild",
+ "fields": {
+ "text": "my text",
+ "nk_fk" : ["apple"],
+ "nk_m2m": [["apple"]]
+ }
+ }
+]
diff --git a/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance2.xml b/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance2.xml
new file mode 100644
index 0000000000..7eb17a6b7e
--- /dev/null
+++ b/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance2.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/regressiontests/fixtures_regress/models.py b/tests/regressiontests/fixtures_regress/models.py
index da8818cd4a..0e727c4935 100644
--- a/tests/regressiontests/fixtures_regress/models.py
+++ b/tests/regressiontests/fixtures_regress/models.py
@@ -52,6 +52,9 @@ class Absolute(models.Model):
class Parent(models.Model):
name = models.CharField(max_length=10)
+ class Meta:
+ ordering = ('id',)
+
class Child(Parent):
data = models.CharField(max_length=10)
@@ -130,6 +133,32 @@ class Book(models.Model):
', '.join(s.name for s in self.stores.all())
)
+class NKManager(models.Manager):
+ def get_by_natural_key(self, data):
+ return self.get(data=data)
+
+class NKChild(Parent):
+ data = models.CharField(max_length=10, unique=True)
+ objects = NKManager()
+
+ def natural_key(self):
+ return self.data
+
+ def __unicode__(self):
+ return u'NKChild %s:%s' % (self.name, self.data)
+
+class RefToNKChild(models.Model):
+ text = models.CharField(max_length=10)
+ nk_fk = models.ForeignKey(NKChild, related_name='ref_fks')
+ nk_m2m = models.ManyToManyField(NKChild, related_name='ref_m2ms')
+
+ def __unicode__(self):
+ return u'%s: Reference to %s [%s]' % (
+ self.text,
+ self.nk_fk,
+ ', '.join(str(o) for o in self.nk_m2m.all())
+ )
+
# ome models with pathological circular dependencies
class Circle1(models.Model):
name = models.CharField(max_length=255)
@@ -244,6 +273,27 @@ No fixture data found for 'bad_fixture2'. (File format may be invalid.)
>>> management.call_command('loaddata', 'model-inheritance.json', verbosity=0)
+###############################################
+# Test for ticket #13030 -- natural keys deserialize with fk to inheriting model
+
+# load data with natural keys
+>>> management.call_command('loaddata', 'nk-inheritance.json', verbosity=0)
+
+>>> NKChild.objects.get(pk=1)
+
+
+>>> RefToNKChild.objects.get(pk=1)
+
+
+# ... and again in XML
+>>> management.call_command('loaddata', 'nk-inheritance2.xml', verbosity=0)
+
+>>> NKChild.objects.get(pk=2)
+
+
+>>> RefToNKChild.objects.get(pk=2)
+
+
###############################################
# Test for ticket #7572 -- MySQL has a problem if the same connection is
# used to create tables, load data, and then query over that data.
@@ -279,7 +329,7 @@ Weight = 1.2 ()
[{"pk": 1, "model": "fixtures_regress.animal", "fields": {"count": 3, "weight": 1.2, "name": "Lion", "latin_name": "Panthera leo"}}, {"pk": 2, "model": "fixtures_regress.animal", "fields": {"count": 2, "weight": 2.2, "name": "Platypus", "latin_name": "Ornithorhynchus anatinus"}}, {"pk": 10, "model": "fixtures_regress.animal", "fields": {"count": 42, "weight": 1.2, "name": "Emu", "latin_name": "Dromaius novaehollandiae"}}]
###############################################
-# Regression for #11428 - Proxy models aren't included when you dumpdata
+# Regression for #11428 - Proxy models aren't included when you dumpdata
# Flush out the database first
>>> management.call_command('reset', 'fixtures_regress', interactive=False, verbosity=0)