Index: django/db/models/sql/query.py
===================================================================
--- django/db/models/sql/query.py	(revision 10454)
+++ django/db/models/sql/query.py	(working copy)
@@ -1391,6 +1391,64 @@
             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 
+                alias = self.join((root_alias, table, f.rel.get_related_field().column, 
+                        f.column), exclusions=used, 
+                        promote=True, 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) 
+
+        # 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
+                alias = self.join((root_alias, table, f.rel.get_related_field().column,
+                        f.column), exclusions=used,
+                        promote=True, 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: django/db/models/options.py
===================================================================
--- django/db/models/options.py	(revision 10454)
+++ django/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: django/db/models/fields/related.py
===================================================================
--- django/db/models/fields/related.py	(revision 10454)
+++ django/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: django/db/models/query.py
===================================================================
--- django/db/models/query.py	(revision 10454)
+++ django/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):
Index: tests/modeltests/select_related_reverse/models.py
===================================================================
--- tests/modeltests/select_related_reverse/models.py	(revision 0)
+++ tests/modeltests/select_related_reverse/models.py	(revision 0)
@@ -0,0 +1,123 @@
+"""
+``select_related()`` follows all forward relationships, but should also follow
+reverse relationships where it is appropriate (currently for OneToOneFields 
+only).
+"""
+
+from django.db import models
+
+# OneToOneField tests only.
+
+class User(models.Model):
+    alias = models.CharField(max_length=20)
+    
+    def __unicode__(self):
+        return 'User, alias = %s' % (self.alias,)
+
+
+class UserInfo(models.Model):
+    user = models.OneToOneField(User, primary_key=True)
+    name = models.CharField(max_length=32)
+
+    def __unicode__(self):
+        return 'UserInfo, name = %s' % (self.name,)
+    
+
+class UserStatResults(models.Model):
+    results = models.CharField(max_length=50)
+
+    def __unicode__(self):
+        return 'UserStatResults, results = %s' % (self.results,)
+    
+
+class UserStat(models.Model):
+    user = models.OneToOneField(User, primary_key=True)
+    posts = models.IntegerField()
+    results = models.ForeignKey(UserStatResults)
+
+    def __unicode__(self):
+        return 'UserStat, posts = %s' % (self.posts,)
+
+
+class StatDetails(models.Model):
+    base_stats = models.OneToOneField(UserStat, primary_key=True)
+    comments = models.IntegerField()
+
+    def __unicode__(self):
+        return 'StatDetails, comments = %s' % (self.comments,)
+
+
+__test__ = {'API_TESTS':"""
+
+# Set up.
+# The test runner sets settings.DEBUG to False, but we want to gather queries
+# so we'll set it to True here and reset it at the end of the test suite.
+>>> from django.conf import settings
+>>> settings.DEBUG = True
+>>> from django import db
+
+>>> usr = UserStatResults.objects.create(results='first results')
+>>> u = User.objects.create(alias='tom')
+>>> ui = UserInfo.objects.create(user=u, name='Tom Jones')
+>>> stat = UserStat.objects.create(user=u, posts=150, results=usr)
+>>> sd = StatDetails.objects.create(base_stats=stat, comments=259)
+>>> u = User.objects.create(alias='john')
+>>> ui = UserInfo.objects.create(user=u, name='John Smith')
+>>> stat = UserStat.objects.create(user=u, posts=33, results=usr)
+>>> sd = StatDetails = StatDetails.objects.create(base_stats=stat, comments=104)
+
+# Specifying models in the select_related(...) works as expected.
+>>> db.reset_queries()
+>>> u = User.objects.select_related('userinfo', 'userstat').get(alias='tom')
+>>> u.userstat
+<UserStat: UserStat, posts = 150>
+>>> len(db.connection.queries)
+1
+>>> u.userstat.statdetails
+<StatDetails: StatDetails, comments = 259>
+>>> len(db.connection.queries)
+2
+>>> u.userinfo
+<UserInfo: UserInfo, name = Tom Jones>
+>>> len(db.connection.queries)
+2
+>>> db.reset_queries()
+>>> u = User.objects.select_related('userstat', 'userstat__statdetails', 'userstat__results').get(alias='tom')
+>>> u.userstat
+<UserStat: UserStat, posts = 150>
+>>> len(db.connection.queries)
+1
+>>> u.userstat.statdetails
+<StatDetails: StatDetails, comments = 259>
+>>> len(db.connection.queries)
+1
+>>> u.userstat.results
+<UserStatResults: UserStatResults, results = first results>
+>>> len(db.connection.queries)
+1
+>>> u.userinfo
+<UserInfo: UserInfo, name = Tom Jones>
+>>> len(db.connection.queries)
+2
+
+>>> db.reset_queries()
+>>> us = UserStat.objects.select_related('user__userinfo').get(user__alias='john')
+>>> us
+<UserStat: UserStat, posts = 33>
+>>> len(db.connection.queries)
+1
+>>> us.user
+<User: User, alias = john>
+>>> len(db.connection.queries)
+1
+>>> us.user.userinfo
+<UserInfo: UserInfo, name = John Smith>
+>>> len(db.connection.queries)
+1
+>>> us.user.userstat
+<UserStat: UserStat, posts = 33>
+>>> len(db.connection.queries)
+1
+
+"""}
+
Index: tests/modeltests/select_related_reverse2/models.py
===================================================================
--- tests/modeltests/select_related_reverse2/models.py	(revision 0)
+++ tests/modeltests/select_related_reverse2/models.py	(revision 0)
@@ -0,0 +1,123 @@
+"""
+``select_related()`` follows all forward relationships, but should also follow
+reverse relationships where it is appropriate (currently for OneToOneFields 
+only).
+"""
+
+from django.db import models
+
+# OneToOneField tests only.
+
+class User(models.Model):
+    alias = models.CharField(max_length=20)
+    
+    def __unicode__(self):
+        return 'User, alias = %s' % (self.alias,)
+
+
+class UserInfo(models.Model):
+    user = models.OneToOneField(User, primary_key=True)
+    name = models.CharField(max_length=32)
+
+    def __unicode__(self):
+        return 'UserInfo, name = %s' % (self.name,)
+    
+
+class UserStatResults(models.Model):
+    results = models.CharField(max_length=50)
+
+    def __unicode__(self):
+        return 'UserStatResults, results = %s' % (self.results,)
+    
+
+class UserStat(models.Model):
+    user = models.ForeignKey(User, primary_key=True, unique=True, related_name='userstat')
+    posts = models.IntegerField()
+    results = models.ForeignKey(UserStatResults)
+
+    def __unicode__(self):
+        return 'UserStat, posts = %s' % (self.posts,)
+
+
+class StatDetails(models.Model):
+    base_stats = models.OneToOneField(UserStat, primary_key=True)
+    comments = models.IntegerField()
+
+    def __unicode__(self):
+        return 'StatDetails, comments = %s' % (self.comments,)
+
+
+__test__ = {'API_TESTS':"""
+
+# Set up.
+# The test runner sets settings.DEBUG to False, but we want to gather queries
+# so we'll set it to True here and reset it at the end of the test suite.
+>>> from django.conf import settings
+>>> settings.DEBUG = True
+>>> from django import db
+
+>>> usr = UserStatResults.objects.create(results='first results')
+>>> u = User.objects.create(alias='tom')
+>>> ui = UserInfo.objects.create(user=u, name='Tom Jones')
+>>> stat = UserStat.objects.create(user=u, posts=150, results=usr)
+>>> sd = StatDetails.objects.create(base_stats=stat, comments=259)
+>>> u = User.objects.create(alias='john')
+>>> ui = UserInfo.objects.create(user=u, name='John Smith')
+>>> stat = UserStat.objects.create(user=u, posts=33, results=usr)
+>>> sd = StatDetails = StatDetails.objects.create(base_stats=stat, comments=104)
+
+# Specifying models in the select_related(...) works as expected.
+>>> db.reset_queries()
+>>> u = User.objects.select_related('userinfo', 'userstat').get(alias='tom')
+>>> u.userstat.all()
+[<UserStat: UserStat, posts = 150>]
+>>> len(db.connection.queries)
+1
+>>> u.userstat.all()[0].statdetails
+<StatDetails: StatDetails, comments = 259>
+>>> len(db.connection.queries)
+2
+>>> u.userinfo
+<UserInfo: UserInfo, name = Tom Jones>
+>>> len(db.connection.queries)
+2
+>>> db.reset_queries()
+>>> u = User.objects.select_related('userstat', 'userstat__statdetails', 'userstat__results').get(alias='tom')
+>>> u.userstat.all()
+[<UserStat: UserStat, posts = 150>]
+>>> len(db.connection.queries)
+1
+>>> u.userstat.all()[0].statdetails
+<StatDetails: StatDetails, comments = 259>
+>>> len(db.connection.queries)
+1
+>>> u.userstat.all()[0].results
+<UserStatResults: UserStatResults, results = first results>
+>>> len(db.connection.queries)
+1
+>>> u.userinfo
+<UserInfo: UserInfo, name = Tom Jones>
+>>> len(db.connection.queries)
+2
+
+>>> db.reset_queries()
+>>> us = UserStat.objects.select_related('user__userinfo').get(user__alias='john')
+>>> us
+<UserStat: UserStat, posts = 33>
+>>> len(db.connection.queries)
+1
+>>> us.user
+<User: User, alias = john>
+>>> len(db.connection.queries)
+1
+>>> us.user.userinfo
+<UserInfo: UserInfo, name = John Smith>
+>>> len(db.connection.queries)
+1
+>>> us.user.userstat.all()
+[<UserStat: UserStat, posts = 33>]
+>>> len(db.connection.queries)
+1
+
+"""}
+
Index: tests/modeltests/select_related_reverse3/models.py
===================================================================
--- tests/modeltests/select_related_reverse3/models.py	(revision 0)
+++ tests/modeltests/select_related_reverse3/models.py	(revision 0)
@@ -0,0 +1,222 @@
+"""
+``select_related()`` follows all forward relationships, but should also follow
+reverse relationships where it is appropriate (currently for OneToOneFields 
+only).
+"""
+
+from django.db import models
+
+# OneToOneField tests only.
+
+class User(models.Model):
+    alias = models.CharField(max_length=20)
+    
+    def __unicode__(self):
+        return 'User, alias = %s' % (self.alias,)
+
+
+class UserInfo(models.Model):
+    user = models.OneToOneField(User, primary_key=True)
+    name = models.CharField(max_length=32)
+
+    def __unicode__(self):
+        return 'UserInfo, name = %s' % (self.name,)
+    
+
+class UserStatResults(models.Model):
+    results = models.CharField(max_length=50)
+
+    def __unicode__(self):
+        return 'UserStatResults, results = %s' % (self.results,)
+    
+
+class UserStat(models.Model):
+    user = models.OneToOneField(User, primary_key=True)
+    posts = models.IntegerField()
+    results = models.ForeignKey(UserStatResults)
+    watcher = models.OneToOneField(User, related_name='stat_watcher')
+
+    def __unicode__(self):
+        return 'UserStat, posts = %s' % (self.posts,)
+
+
+class StatDetails(models.Model):
+    base_stats = models.OneToOneField(UserStat, primary_key=True)
+    comments = models.IntegerField()
+
+    def __unicode__(self):
+        return 'StatDetails, comments = %s' % (self.comments,)
+
+
+__test__ = {'API_TESTS':"""
+
+# Set up.
+# The test runner sets settings.DEBUG to False, but we want to gather queries
+# so we'll set it to True here and reset it at the end of the test suite.
+>>> from django.conf import settings
+>>> settings.DEBUG = True
+>>> from django import db
+
+>>> usr = UserStatResults.objects.create(results='first results')
+>>> u1 = User.objects.create(alias='tom')
+>>> ui = UserInfo.objects.create(user=u1, name='Tom Jones')
+>>> u2 = User.objects.create(alias='john')
+>>> ui = UserInfo.objects.create(user=u2, name='John Smith')
+>>> u3 = User.objects.create(alias='bob')
+>>> ui = UserInfo.objects.create(user=u3, name='Bob Rogers')
+>>> stat = UserStat.objects.create(user=u1, posts=150, results=usr, watcher=u3)
+>>> sd = StatDetails.objects.create(base_stats=stat, comments=259)
+>>> stat = UserStat.objects.create(user=u2, posts=33, results=usr, watcher=u2)
+>>> sd = StatDetails = StatDetails.objects.create(base_stats=stat, comments=104)
+
+# Specifying models in the select_related(...) works as expected.
+>>> db.reset_queries()
+>>> u = User.objects.select_related('userinfo', 'userstat').get(alias='tom')
+>>> u.userstat
+<UserStat: UserStat, posts = 150>
+>>> len(db.connection.queries)
+1
+>>> u.userstat.statdetails
+<StatDetails: StatDetails, comments = 259>
+>>> len(db.connection.queries)
+2
+>>> u.userinfo
+<UserInfo: UserInfo, name = Tom Jones>
+>>> len(db.connection.queries)
+2
+>>> db.reset_queries()
+>>> u = User.objects.select_related('userstat', 'userstat__statdetails', 'userstat__results').get(alias='tom')
+>>> u.userstat
+<UserStat: UserStat, posts = 150>
+>>> len(db.connection.queries)
+1
+>>> u.userstat.statdetails
+<StatDetails: StatDetails, comments = 259>
+>>> len(db.connection.queries)
+1
+>>> u.userstat.results
+<UserStatResults: UserStatResults, results = first results>
+>>> len(db.connection.queries)
+1
+>>> u.userinfo
+<UserInfo: UserInfo, name = Tom Jones>
+>>> len(db.connection.queries)
+2
+
+>>> db.reset_queries()
+>>> us = UserStat.objects.select_related('user__userinfo').get(user__alias='john')
+>>> us
+<UserStat: UserStat, posts = 33>
+>>> len(db.connection.queries)
+1
+>>> us.user
+<User: User, alias = john>
+>>> len(db.connection.queries)
+1
+>>> us.user.userinfo
+<UserInfo: UserInfo, name = John Smith>
+>>> len(db.connection.queries)
+1
+>>> us.user.userstat
+<UserStat: UserStat, posts = 33>
+>>> len(db.connection.queries)
+1
+
+# !!!!!!!!!!!!!!
+# Everything past this point is testing multiple fields pointing to the same model.
+# !!!!!!!!!!!!!!
+>>> us.user.userstat.watcher
+<User: User, alias = john>
+>>> len(db.connection.queries)
+2
+
+>>> db.reset_queries()
+>>> us = UserStat.objects.select_related('user__userinfo', 'watcher').get(user__alias='john')
+>>> us
+<UserStat: UserStat, posts = 33>
+>>> len(db.connection.queries)
+1
+>>> us.user
+<User: User, alias = john>
+>>> len(db.connection.queries)
+1
+>>> us.user.userinfo
+<UserInfo: UserInfo, name = John Smith>
+>>> len(db.connection.queries)
+1
+>>> us.user.userstat
+<UserStat: UserStat, posts = 33>
+>>> len(db.connection.queries)
+1
+
+>>> us.user.userstat.watcher
+<User: User, alias = john>
+>>> len(db.connection.queries)
+1
+
+# Show that the # of queries increases as expected when used reverse.
+>>> db.reset_queries()
+>>> u = User.objects.select_related('userinfo', 'userstat').get(alias='tom')
+>>> u.userstat
+<UserStat: UserStat, posts = 150>
+>>> len(db.connection.queries)
+1
+>>> u.userstat.statdetails
+<StatDetails: StatDetails, comments = 259>
+>>> len(db.connection.queries)
+2
+>>> u.userstat.watcher
+<User: User, alias = bob>
+>>> len(db.connection.queries)
+3
+>>> u.userinfo
+<UserInfo: UserInfo, name = Tom Jones>
+>>> len(db.connection.queries)
+3
+
+# Show that we can follow the watcher too.
+>>> db.reset_queries()
+>>> u = User.objects.select_related('userinfo', 'userstat').get(alias='john')
+>>> u.userstat
+<UserStat: UserStat, posts = 33>
+>>> len(db.connection.queries)
+1
+>>> u.userstat.watcher
+<User: User, alias = john>
+>>> len(db.connection.queries)
+2
+>>> u.stat_watcher
+<UserStat: UserStat, posts = 33>
+>>> len(db.connection.queries)
+3
+
+# Show that we can follow the watcher via the select_related(...) bits.
+>>> db.reset_queries()
+>>> u = User.objects.select_related('userstat', 'stat_watcher').get(alias='john')
+>>> u.userstat
+<UserStat: UserStat, posts = 33>
+>>> len(db.connection.queries)
+1
+>>> u.userstat.watcher
+<User: User, alias = john>
+>>> len(db.connection.queries)
+2
+>>> u.stat_watcher
+<UserStat: UserStat, posts = 33>
+>>> len(db.connection.queries)
+2
+
+# Show that we can follow the watcher via the select_related(...) bits that are nested.
+>>> db.reset_queries()
+>>> u = User.objects.select_related('userstat', 'userstat__watcher').get(alias='tom')
+>>> u.userstat
+<UserStat: UserStat, posts = 150>
+>>> len(db.connection.queries)
+1
+>>> u.userstat.watcher
+<User: User, alias = bob>
+>>> len(db.connection.queries)
+1
+
+"""}
+
