Index: django/db/models/base.py
===================================================================
--- django/db/models/base.py	(revision 10338)
+++ django/db/models/base.py	(working copy)
@@ -362,9 +362,8 @@
                     # DeferredAttribute classes, so we only need to do this
                     # once.
                     obj = self.__class__.__dict__[field.attname]
-                    pk_val = obj.pk_value
                     model = obj.model_ref()
-        return (model_unpickle, (model, pk_val, defers), data)
+        return (model_unpickle, (model, defers), data)
 
     def _get_pk_val(self, meta=None):
         if not meta:
@@ -635,12 +634,12 @@
 class Empty(object):
     pass
 
-def model_unpickle(model, pk_val, attrs):
+def model_unpickle(model, attrs):
     """
     Used to unpickle Model subclasses with deferred fields.
     """
     from django.db.models.query_utils import deferred_class_factory
-    cls = deferred_class_factory(model, pk_val, attrs)
+    cls = deferred_class_factory(model, attrs)
     return cls.__new__(cls)
 model_unpickle.__safe_for_unpickle__ = True
 
Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py	(revision 10338)
+++ django/db/models/query.py	(working copy)
@@ -190,6 +190,20 @@
         index_start = len(extra_select)
         aggregate_start = index_start + len(self.model._meta.fields)
 
+        load_fields = only_load.get(self.model)
+        skip = None
+        if load_fields and not fill_cache:
+            # Some fields have been deferred, so we have to initialise
+            # via keyword arguments.
+            skip = set()
+            init_list = []
+            for field in fields:
+                if field.name not in load_fields:
+                    skip.add(field.attname)
+                else:
+                    init_list.append(field.attname)
+            model_cls = deferred_class_factory(self.model, skip)
+
         for row in self.query.results_iter():
             if fill_cache:
                 obj, _ = get_cached_row(self.model, row,
@@ -197,25 +211,10 @@
                             requested=requested, offset=len(aggregate_select),
                             only_load=only_load)
             else:
-                load_fields = only_load.get(self.model)
-                if load_fields:
-                    # Some fields have been deferred, so we have to initialise
-                    # via keyword arguments.
+                if skip:
                     row_data = row[index_start:aggregate_start]
                     pk_val = row_data[pk_idx]
-                    skip = set()
-                    init_list = []
-                    for field in fields:
-                        if field.name not in load_fields:
-                            skip.add(field.attname)
-                        else:
-                            init_list.append(field.attname)
-                    if skip:
-                        model_cls = deferred_class_factory(self.model, pk_val,
-                                skip)
-                        obj = model_cls(**dict(zip(init_list, row_data)))
-                    else:
-                        obj = self.model(*row[index_start:aggregate_start])
+                    obj = model_cls(**dict(zip(init_list, row_data)))
                 else:
                     # Omit aggregates in object creation.
                     obj = self.model(*row[index_start:aggregate_start])
@@ -927,7 +926,7 @@
                 else:
                     init_list.append(field.attname)
             if skip:
-                klass = deferred_class_factory(klass, pk_val, skip)
+                klass = deferred_class_factory(klass, skip)
                 obj = klass(**dict(zip(init_list, fields)))
             else:
                 obj = klass(*fields)
Index: django/db/models/query_utils.py
===================================================================
--- django/db/models/query_utils.py	(revision 10338)
+++ django/db/models/query_utils.py	(working copy)
@@ -158,9 +158,8 @@
     A wrapper for a deferred-loading field. When the value is read from this
     object the first time, the query is executed.
     """
-    def __init__(self, field_name, pk_value, model):
+    def __init__(self, field_name, model):
         self.field_name = field_name
-        self.pk_value = pk_value
         self.model_ref = weakref.ref(model)
         self.loaded = False
 
@@ -170,22 +169,30 @@
         Returns the cached value.
         """
         assert instance is not None
-        if not self.loaded:
-            obj = self.model_ref()
-            if obj is None:
-                return
-            self.value = list(obj._base_manager.filter(pk=self.pk_value).values_list(self.field_name, flat=True))[0]
-            self.loaded = True
-        return self.value
+        cls = self.model_ref()
+        field = self.get_field(cls)
+        if not hasattr(instance, field.get_cache_name()):
+            setattr(instance, field.get_cache_name(), cls._base_manager.filter(pk=instance.pk).values_list(self.field_name, flat=True).get())
+        return getattr(instance, field.get_cache_name())
 
-    def __set__(self, name, value):
+    def __set__(self, instance, value):
         """
         Deferred loading attributes can be set normally (which means there will
         never be a database lookup involved.
         """
-        self.value = value
-        self.loaded = True
+        field = self.get_field(self.model_ref())
+        setattr(instance, field.get_cache_name(), value)
 
+    def get_field(self, model):
+        """
+        This is used instead of model._meta.get_field() because we need to
+        retrive the field by attribute name rather than field name.
+        """
+        for field in model._meta.fields:
+            if field.attname == self.field_name:
+                break
+        return field
+
 def select_related_descend(field, restricted, requested):
     """
     Returns True if this field should be used to descend deeper for
@@ -206,7 +213,7 @@
 # This function is needed because data descriptors must be defined on a class
 # object, not an instance, to have any effect.
 
-def deferred_class_factory(model, pk_value, attrs):
+def deferred_class_factory(model, attrs):
     """
     Returns a class object that is a copy of "model" with the specified "attrs"
     being replaced with DeferredAttribute objects. The "pk_value" ties the
@@ -223,7 +230,7 @@
     # are identical.
     name = "%s_Deferred_%s" % (model.__name__, '_'.join(sorted(list(attrs))))
 
-    overrides = dict([(attr, DeferredAttribute(attr, pk_value, model))
+    overrides = dict([(attr, DeferredAttribute(attr, model))
             for attr in attrs])
     overrides["Meta"] = Meta
     overrides["__module__"] = model.__module__
@@ -233,4 +240,3 @@
 # The above function is also used to unpickle model instances with deferred
 # fields.
 deferred_class_factory.__safe_for_unpickling__ = True
-
Index: django/contrib/gis/tests/relatedapp/tests.py
===================================================================
--- django/contrib/gis/tests/relatedapp/tests.py	(revision 10338)
+++ django/contrib/gis/tests/relatedapp/tests.py	(working copy)
@@ -183,13 +183,12 @@
             self.assertEqual(m.point, d['point'])
             self.assertEqual(m.point, t[1])
 
-    # Test disabled until #10572 is resolved.
-    #def test08_defer_only(self):
-    #    "Testing defer() and only() on Geographic models."
-    #    qs = Location.objects.all()
-    #    def_qs = Location.objects.defer('point')
-    #    for loc, def_loc in zip(qs, def_qs):
-    #        self.assertEqual(loc.point, def_loc.point)
+    def test08_defer_only(self):
+        "Testing defer() and only() on Geographic models."
+        qs = Location.objects.all()
+        def_qs = Location.objects.defer('point')
+        for loc, def_loc in zip(qs, def_qs):
+            self.assertEqual(loc.point, def_loc.point)
 
     # TODO: Related tests for KML, GML, and distance lookups.
 
Index: tests/regressiontests/defer_regress/models.py
===================================================================
--- tests/regressiontests/defer_regress/models.py	(revision 10338)
+++ tests/regressiontests/defer_regress/models.py	(working copy)
@@ -6,7 +6,7 @@
 from django.db import connection, models
 
 class Item(models.Model):
-    name = models.CharField(max_length=10)
+    name = models.CharField(max_length=20)
     text = models.TextField(default="xyzzy")
     value = models.IntegerField()
     other_value = models.IntegerField(default=0)
@@ -40,8 +40,14 @@
 >>> len(connection.queries) == num + 2      # Effect of text lookup.
 True
 
+>>> _ = Item.objects.create(name="no I'm first", value=37)
+>>> items = Item.objects.only('value').order_by('-value')
+>>> items[0].name
+u'first'
+>>> items[1].name
+u"no I'm first"
+
 >>> settings.DEBUG = False
 
 """
 }
-
