Index: tests/regressiontests/m2m_regress/tests.py
===================================================================
--- tests/regressiontests/m2m_regress/tests.py	(revision 16522)
+++ tests/regressiontests/m2m_regress/tests.py	(working copy)
@@ -73,3 +73,14 @@
 
         self.assertQuerysetEqual(c1.tags.all(), ["<Tag: t1>", "<Tag: t2>"])
         self.assertQuerysetEqual(t1.tag_collections.all(), ["<TagCollection: c1>"])
+
+    def test_manager_class(self):
+        e1 = Entry.objects.create()
+        e2 = Entry.objects.create()
+        t1 = Tag.objects.create()
+        t2 = Tag.objects.create()
+        self.assertTrue(e1.topics.__class__ is e1.topics.__class__)
+        self.assertTrue(e2.topics.__class__ is e2.topics.__class__)
+
+        self.assertTrue(t1.entry_set.__class__ is t1.entry_set.__class__)
+        self.assertTrue(t1.entry_set.__class__ is t2.entry_set.__class__)
Index: django/db/models/fields/related.py
===================================================================
--- django/db/models/fields/related.py	(revision 16522)
+++ django/db/models/fields/related.py	(working copy)
@@ -11,7 +11,7 @@
 from django.utils.encoding import smart_unicode
 from django.utils.translation import (ugettext_lazy as _, string_concat,
     ungettext, ugettext)
-from django.utils.functional import curry
+from django.utils.functional import curry, cached_property, memoize
 from django.core import exceptions
 from django import forms
 
@@ -387,10 +387,11 @@
     def __get__(self, instance, instance_type=None):
         if instance is None:
             return self
+        manager = self.create_manager(
+            self.related.model._default_manager.__class__
+        )
+        return manager(instance)
 
-        return self.create_manager(instance,
-                self.related.model._default_manager.__class__)
-
     def __set__(self, instance, value):
         if instance is None:
             raise AttributeError("Manager must be accessed via instance")
@@ -408,10 +409,10 @@
         than the default manager, as returned by __get__). Used by
         Model.delete().
         """
-        return self.create_manager(instance,
-                self.related.model._base_manager.__class__)
+        manager = self.create_manager(self.related.model._base_manager.__class__)
+        return manager(instance)
 
-    def create_manager(self, instance, superclass):
+    def create_manager(self, superclass):
         """
         Creates the managers used by other methods (__get__() and delete()).
         """
@@ -419,57 +420,64 @@
         rel_model = self.related.model
 
         class RelatedManager(superclass):
+            def __init__(self, instance):
+                super(RelatedManager, self).__init__()
+                attname = rel_field.rel.get_related_field().name
+                self.instance = instance
+                self.core_filters = {
+                    '%s__%s' % (rel_field.name, attname): getattr(instance, attname)
+                }
+                self.model = rel_model
+            
             def get_query_set(self):
-                db = self._db or router.db_for_read(rel_model, instance=instance)
-                return superclass.get_query_set(self).using(db).filter(**(self.core_filters))
+                db = self._db or router.db_for_read(
+                    rel_model, instance=self.instance
+                )
+                return superclass.get_query_set(self).using(db).filter(**self.core_filters)
 
             def add(self, *objs):
                 for obj in objs:
                     if not isinstance(obj, self.model):
                         raise TypeError("'%s' instance expected" % self.model._meta.object_name)
-                    setattr(obj, rel_field.name, instance)
+                    setattr(obj, rel_field.name, self.instance)
                     obj.save()
             add.alters_data = True
 
             def create(self, **kwargs):
-                kwargs.update({rel_field.name: instance})
-                db = router.db_for_write(rel_model, instance=instance)
+                kwargs.update({rel_field.name: self.instance})
+                db = router.db_for_write(rel_model, instance=self.instance)
                 return super(RelatedManager, self.db_manager(db)).create(**kwargs)
             create.alters_data = True
 
             def get_or_create(self, **kwargs):
                 # Update kwargs with the related object that this
                 # ForeignRelatedObjectsDescriptor knows about.
-                kwargs.update({rel_field.name: instance})
-                db = router.db_for_write(rel_model, instance=instance)
+                kwargs.update({rel_field.name: self.instance})
+                db = router.db_for_write(rel_model, instance=self.instance)
                 return super(RelatedManager, self.db_manager(db)).get_or_create(**kwargs)
             get_or_create.alters_data = True
 
-            # remove() and clear() are only provided if the ForeignKey can have a value of null.
+            # remove() and clear() are only provided if the ForeignKey can have
+            # a value of null.
             if rel_field.null:
                 def remove(self, *objs):
-                    val = getattr(instance, rel_field.rel.get_related_field().attname)
+                    val = getattr(self.instance, rel_field.rel.get_related_field().attname)
                     for obj in objs:
                         # Is obj actually part of this descriptor set?
                         if getattr(obj, rel_field.attname) == val:
                             setattr(obj, rel_field.name, None)
                             obj.save()
                         else:
-                            raise rel_field.rel.to.DoesNotExist("%r is not related to %r." % (obj, instance))
+                            raise rel_field.rel.to.DoesNotExist("%r is not related to %r." % (obj, self.instance))
                 remove.alters_data = True
 
                 def clear(self):
                     self.update(**{rel_field.name: None})
                 clear.alters_data = True
 
-        manager = RelatedManager()
-        attname = rel_field.rel.get_related_field().name
-        manager.core_filters = {'%s__%s' % (rel_field.name, attname):
-                getattr(instance, attname)}
-        manager.model = self.related.model
+        return RelatedManager
+    create_manager = memoize(create_manager, {}, 2)
 
-        return manager
-
 def create_many_related_manager(superclass, rel=False):
     """Creates a manager that subclasses 'superclass' (which is a Manager)
     and adds behavior for many-to-many related objects."""
@@ -657,18 +665,22 @@
     # ManyRelatedObjectsDescriptor instance.
     def __init__(self, related):
         self.related = related   # RelatedObject instance
+    
+    @cached_property
+    def related_manager_cls(self):
+        # Dynamically create a class that subclasses the related
+        # model's default manager.
+        return create_many_related_manager(
+            self.related.model._default_manager.__class__,
+            self.related.field.rel
+        )
 
     def __get__(self, instance, instance_type=None):
         if instance is None:
             return self
 
-        # Dynamically create a class that subclasses the related
-        # model's default manager.
         rel_model = self.related.model
-        superclass = rel_model._default_manager.__class__
-        RelatedManager = create_many_related_manager(superclass, self.related.field.rel)
-
-        manager = RelatedManager(
+        manager = self.related_manager_cls(
             model=rel_model,
             core_filters={'%s__pk' % self.related.field.name: instance._get_pk_val()},
             instance=instance,
@@ -702,6 +714,15 @@
     # ReverseManyRelatedObjectsDescriptor instance.
     def __init__(self, m2m_field):
         self.field = m2m_field
+    
+    @cached_property
+    def related_manager_cls(self):
+        # Dynamically create a class that subclasses the related model's
+        # default manager.
+        return create_many_related_manager(
+            self.field.rel.to._default_manager.__class__,
+            self.field.rel
+        )
 
     def _through(self):
         # through is provided so that you have easy access to the through
@@ -713,15 +734,9 @@
     def __get__(self, instance, instance_type=None):
         if instance is None:
             return self
-
-        # Dynamically create a class that subclasses the related
-        # model's default manager.
-        rel_model=self.field.rel.to
-        superclass = rel_model._default_manager.__class__
-        RelatedManager = create_many_related_manager(superclass, self.field.rel)
-
-        manager = RelatedManager(
-            model=rel_model,
+        
+        manager = self.related_manager_cls(
+            model=self.field.rel.to,
             core_filters={'%s__pk' % self.field.related_query_name(): instance._get_pk_val()},
             instance=instance,
             symmetrical=self.field.rel.symmetrical,
@@ -1041,7 +1056,7 @@
         if hasattr(self, cache_attr):
             return getattr(self, cache_attr)
         for f in self.rel.through._meta.fields:
-            if hasattr(f,'rel') and f.rel and f.rel.to == related.model:
+            if hasattr(f, 'rel') and f.rel and f.rel.to == related.model:
                 setattr(self, cache_attr, getattr(f, attr))
                 return getattr(self, cache_attr)
 
Index: django/utils/functional.py
===================================================================
--- django/utils/functional.py	(revision 16522)
+++ django/utils/functional.py	(working copy)
@@ -28,6 +28,14 @@
         return result
     return wrapper
 
+class cached_property(object):
+    def __init__(self, func):
+        self.func = func
+    
+    def __get__(self, instance, type):
+        res = instance.__dict__[self.func.__name__] = self.func(instance)
+        return res
+
 class Promise(object):
     """
     This is just a base class for the proxy class created in
