Index: django/db/models/manager.py
===================================================================
--- django/db/models/manager.py	(revision 4431)
+++ django/db/models/manager.py	(working copy)
@@ -101,6 +101,9 @@
 
     def select_related(self, *args, **kwargs):
         return self.get_query_set().select_related(*args, **kwargs)
+    
+    def auto_cache(self, *args, **kwargs):
+        return self.get_query_set().auto_cache(*args, **kwargs)
 
     def values(self, *args, **kwargs):
         return self.get_query_set().values(*args, **kwargs)
Index: django/db/models/fields/related.py
===================================================================
--- django/db/models/fields/related.py	(revision 4431)
+++ django/db/models/fields/related.py	(working copy)
@@ -135,9 +135,9 @@
         # Set the value of the related field
         setattr(value, self.related.field.rel.get_related_field().attname, instance)
 
-        # Clear the cache, if it exists
+        # Update the cache, if it exists
         try:
-            delattr(value, self.related.field.get_cache_name())
+            setattr(value, self.related.field.get_cache_name(), value)
         except AttributeError:
             pass
 
@@ -182,9 +182,9 @@
             val = None
         setattr(instance, self.field.attname, val)
 
-        # Clear the cache, if it exists
+        # Update the cache, if it exists
         try:
-            delattr(instance, self.field.get_cache_name())
+            setattr(instance, self.field.get_cache_name(), value)
         except AttributeError:
             pass
 
@@ -210,7 +210,7 @@
 
         class RelatedManager(superclass):
             def get_query_set(self):
-                return superclass.get_query_set(self).filter(**(self.core_filters))
+                return superclass.get_query_set(self).filter(**(self.core_filters)).auto_cache(**self.core_cache)
 
             def add(self, *objs):
                 for obj in objs:
@@ -245,6 +245,7 @@
 
         manager = RelatedManager()
         manager.core_filters = {'%s__pk' % rel_field.name: getattr(instance, rel_field.rel.get_related_field().attname)}
+        manager.core_cache = { rel_field.name: instance }
         manager.model = self.related.model
 
         return manager
Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py	(revision 4431)
+++ django/db/models/query.py	(working copy)
@@ -91,6 +91,7 @@
         self._tables = []            # List of extra tables to use.
         self._offset = None          # OFFSET clause.
         self._limit = None           # LIMIT clause.
+        self._auto_cache = {}        # Dictionary of items to automatically cache on the fetched objects.
         self._result_cache = None
 
     ########################
@@ -192,6 +193,9 @@
                     obj = self.model(*row[:index_end])
                 for i, k in enumerate(extra_select):
                     setattr(obj, k[0], row[index_end+i])
+                # auto cache items
+                for key in self._auto_cache:
+                  setattr(obj, key, self._auto_cache[key])
                 yield obj
 
     def count(self):
@@ -386,6 +390,13 @@
     def distinct(self, true_or_false=True):
         "Returns a new QuerySet instance with '_distinct' modified."
         return self._clone(_distinct=true_or_false)
+    
+    def auto_cache(self, **kwargs):
+        """"Returns a new QuerySet instance with _auto_cache modified.
+        This is not available publicly.  It is used to automatically cache
+        the reverse foreign key assocaiation when getting an object through
+        a FOO_set. """
+        return self._clone(_auto_cache=kwargs)
 
     def extra(self, select=None, where=None, params=None, tables=None):
         assert self._limit is None and self._offset is None, \
@@ -416,6 +427,7 @@
         c._tables = self._tables[:]
         c._offset = self._offset
         c._limit = self._limit
+        c._auto_cache = self._auto_cache.copy()
         c.__dict__.update(kwargs)
         return c
 
Index: tests/modeltests/many_to_one/models.py
===================================================================
--- tests/modeltests/many_to_one/models.py	(revision 4431)
+++ tests/modeltests/many_to_one/models.py	(working copy)
@@ -245,6 +245,16 @@
 >>> Reporter.objects.filter(article__reporter=r).distinct()
 [<Reporter: John Smith>]
 
+# Automatic caching
+>>> r_ac = Reporter.objects.all()[0]
+>>> r_ac
+<Reporter: John Smith>
+>>> a_ac = r_ac.article_set.all()[0]
+>>> a_ac
+<Article: John's second story>
+>>> a_ac.reporter is r_ac
+True
+
 # If you delete a reporter, his articles will be deleted.
 >>> Article.objects.all()
 [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>, <Article: This is a test>, <Article: This is a test>]
Index: docs/db-api.txt
===================================================================
--- docs/db-api.txt	(revision 4431)
+++ docs/db-api.txt	(working copy)
@@ -1446,6 +1446,14 @@
     b.entry_set.filter(headline__contains='Lennon')
     b.entry_set.count()
 
+Note that the reverse association from the foreign key is automatically cached
+when retrieving objects through this ``Manager``.
+
+Example::
+    b = Blog.objects.get(id=1)
+    for entry in b.entry_set.all():
+        entry.blog # No database access required.
+
 You can override the ``FOO_set`` name by setting the ``related_name``
 parameter in the ``ForeignKey()`` definition. For example, if the ``Entry``
 model was altered to ``blog = ForeignKey(Blog, related_name='entries')``, the
