diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py index a68ea21f78..6cdfc9f240 100644 --- a/django/core/serializers/python.py +++ b/django/core/serializers/python.py @@ -45,18 +45,12 @@ class Serializer(base.Serializer): self._current[field.name] = field.value_to_string(obj) def handle_fk_field(self, obj, field): - related = getattr(obj, field.name) - if related is not None: - if self.use_natural_keys and hasattr(related, 'natural_key'): - related = related.natural_key() - else: - if field.rel.field_name == related._meta.pk.name: - # Related to remote object via primary key - related = related._get_pk_val() - else: - # Related to remote object via other field - related = smart_unicode(getattr(related, field.rel.field_name), strings_only=True) - self._current[field.name] = related + if self.use_natural_keys and hasattr(field.rel.to, 'natural_key'): + related = getattr(obj, field.name) + value = related.natural_key() + else: + value = getattr(obj, field.get_attname()) + self._current[field.name] = value def handle_m2m_field(self, obj, field): if field.rel.through._meta.auto_created: diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index bcf5631e00..a5edeac5af 100644 --- a/django/core/serializers/xml_serializer.py +++ b/django/core/serializers/xml_serializer.py @@ -85,9 +85,10 @@ class Serializer(base.Serializer): differently from regular fields). """ self._start_relational_field(field) - related = getattr(obj, field.name) - if related is not None: - if self.use_natural_keys and hasattr(related, 'natural_key'): + related_att = getattr(obj, field.get_attname()) + if related_att is not None: + if self.use_natural_keys and hasattr(field.rel.to, 'natural_key'): + related = getattr(obj, field.name) # If related object has a natural key, use it related = related.natural_key() # Iterable natural keys are rolled out as subelements @@ -96,13 +97,7 @@ class Serializer(base.Serializer): self.xml.characters(smart_unicode(key_value)) self.xml.endElement("natural") else: - if field.rel.field_name == related._meta.pk.name: - # Related to remote object via primary key - related = related._get_pk_val() - else: - # Related to remote object via other field - related = getattr(related, field.rel.field_name) - self.xml.characters(smart_unicode(related)) + self.xml.characters(smart_unicode(related_att)) else: self.xml.addQuickElement("None") self.xml.endElement("field") diff --git a/tests/modeltests/serializers/tests.py b/tests/modeltests/serializers/tests.py index 721ca09282..309a83e8b4 100644 --- a/tests/modeltests/serializers/tests.py +++ b/tests/modeltests/serializers/tests.py @@ -178,6 +178,19 @@ class SerializersTestBase(object): mv_obj = obj_list[0].object self.assertEqual(mv_obj.title, movie_title) + def test_serialize_superfluous_queries(self): + """Ensure no superfluous queries are made when serializing ForeignKeys + + #17602 + """ + ac = Actor(name='Actor name') + ac.save() + mv = Movie(title='Movie title', actor_id=ac.pk) + mv.save() + + with self.assertNumQueries(0): + serial_str = serializers.serialize(self.serializer_name, [mv]) + def test_serialize_with_null_pk(self): """ Tests that serialized data with no primary key results