Index: db/models/sql/query.py
===================================================================
--- db/models/sql/query.py	(revision 10448)
+++ db/models/sql/query.py	(working copy)
@@ -1391,6 +1391,38 @@
             self.fill_related_selections(f.rel.to._meta, alias, cur_depth + 1,
                     used, next, restricted, new_nullable, dupe_set, avoid)
 
+	# Do reverse columns, but only the ones in the requested list. 
+        if restricted: 
+            related_fields = [(x.field, x.model) for x in opts.get_all_related_objects() if x.field.unique] 
+            for f, model in related_fields: 
+                if f.rel.parent_link or f.related_query_name() not in requested: 
+                    continue 
+                table = model._meta.db_table 
+                if nullable or f.null: 
+                    promote = True 
+                else: 
+                    promote = False 
+                alias = self.join((root_alias, table, f.rel.get_related_field().column, 
+                        f.column), exclusions=used, 
+                        promote=promote, reuse=used) 
+                used.add(alias) 
+ 
+                self.related_select_cols.extend([(alias, f2.column) 
+                        for f2 in model._meta.fields]) 
+                self.related_select_fields.extend(model._meta.fields) 
+ 
+                next = requested.get(f.related_query_name(), {}) 
+                #if nullable is not None: 
+                #    new_nullable = nullable 
+                #else: 
+                #    new_nullable = f.null 
+                if f.null is not None: 
+                    new_nullable = f.null 
+                else: 
+                    new_nullable = None 
+                self.fill_related_selections(model._meta, table, cur_depth + 1, 
+                        used, next, restricted, new_nullable) 
+
     def add_aggregate(self, aggregate, model, alias, is_summary):
         """
         Adds a single aggregate expression to the Query
Index: db/models/options.py
===================================================================
--- db/models/options.py	(revision 10448)
+++ db/models/options.py	(working copy)
@@ -47,6 +47,7 @@
         self.proxy_for_model = None
         self.parents = SortedDict()
         self.duplicate_targets = {}
+        self.reverse_field_cache = {}
 
         # To handle various inheritance situations, we need to track where
         # managers came from (concrete or abstract base classes).
Index: db/models/fields/related.py
===================================================================
--- db/models/fields/related.py	(revision 10448)
+++ db/models/fields/related.py	(working copy)
@@ -1,3 +1,4 @@
+import types
 from django.db import connection, transaction
 from django.db.backends import util
 from django.db.models import signals, get_model
@@ -178,7 +179,11 @@
     # SingleRelatedObjectDescriptor instance.
     def __init__(self, related):
         self.related = related
-        self.cache_name = '_%s_cache' % related.get_accessor_name()
+        #self.cache_name = '_%s_cache' % related.get_accessor_name()
+        cache_name = '_%s_cache' % related.field.related_query_name() 
+        # Contribute to the parent model for later lookup. 
+        related.parent_model._meta.reverse_field_cache[related.field.related_query_name()] = cache_name 
+        self.cache_name = cache_name 
 
     def __get__(self, instance, instance_type=None):
         if instance is None:
@@ -291,6 +296,11 @@
     # attribute is a ForeignRelatedObjectsDescriptor instance.
     def __init__(self, related):
         self.related = related   # RelatedObject instance
+        if related.field.unique: 
+            cache_name = '_%s_cache' % related.field.related_query_name() 
+            # Contribute to the parent model for later lookup. 
+            related.parent_model._meta.reverse_field_cache[related.field.related_query_name()] = cache_name 
+            self.cache_name = cache_name 
 
     def __get__(self, instance, instance_type=None):
         if instance is None:
@@ -309,6 +319,9 @@
         if self.related.field.null:
             manager.clear()
         manager.add(*value)
+        # Cache the value specially if from a unique set. 
+        if self.related.field.unique:
+            self.cache_name = value
 
     def delete_manager(self, instance):
         """
@@ -325,6 +338,8 @@
         """
         rel_field = self.related.field
         rel_model = self.related.model
+	if rel_field.unique:
+            cache_name = self.cache_name 
 
         class RelatedManager(superclass):
             def get_query_set(self):
@@ -369,6 +384,17 @@
                         obj.save()
                 clear.alters_data = True
 
+            if rel_field.unique:
+	        def all(self): 
+                    try: 
+                        result = getattr(instance, cache_name) 
+                        if isinstance(result, (types.TupleType, types.ListType)): 
+                            return result 
+                        else: 
+                            return [result] 
+                    except AttributeError, ae: 
+                        return superclass.get_query_set(self) 
+
         manager = RelatedManager()
         attname = rel_field.rel.get_related_field().name
         manager.core_filters = {'%s__%s' % (rel_field.name, attname):
Index: db/models/query.py
===================================================================
--- db/models/query.py	(revision 10448)
+++ db/models/query.py	(working copy)
@@ -937,6 +937,7 @@
             obj = klass(*fields)
 
     index_end = index_start + field_count + offset
+
     for f in klass._meta.fields:
         if not select_related_descend(f, restricted, requested):
             continue
@@ -950,6 +951,30 @@
             rel_obj, index_end = cached_row
             if obj is not None:
                 setattr(obj, f.get_cache_name(), rel_obj)
+
+            # Do the reverse cache if the field is a unique relation.
+            if f.unique:
+                cache_var_name = rel_obj._meta.reverse_field_cache[f.related_query_name()]
+                setattr(rel_obj, cache_var_name, obj)
+
+    if restricted:
+        related_fields = [(x.field, x.model) for x in klass._meta.get_all_related_objects() if x.field.unique]
+        for f, model in related_fields:
+            if f.related_query_name() not in requested:
+                continue
+
+            next = requested.get(f.related_query_name(), {})
+            cached_row = get_cached_row(model, row, index_end, max_depth,
+                    cur_depth+1, next)
+            if cached_row:
+                rel_obj, index_end = cached_row
+                if rel_obj is not None:
+                    setattr(rel_obj, f.get_cache_name(), obj)
+
+                # Now do the reverse cache.
+                cache_var_name = obj._meta.reverse_field_cache[f.related_query_name()]
+                setattr(obj, cache_var_name, rel_obj)
+
     return obj, index_end
 
 def delete_objects(seen_objs):
