Index: django/db/models/fields/related.py
===================================================================
--- django/db/models/fields/related.py	(revision 7523)
+++ django/db/models/fields/related.py	(working copy)
@@ -103,13 +103,15 @@
 
         if hasattr(sup, 'contribute_to_class'):
             sup.contribute_to_class(cls, name)
+
+        if not cls._meta.abstract and self.rel.related_name:
+            self.rel.related_name = self.rel.related_name % {'class': cls.__name__.lower()}
+
         other = self.rel.to
         if isinstance(other, basestring):
             add_lazy_relation(cls, self, other)
         else:
             self.do_related_class(other, cls)
-        if not cls._meta.abstract and self.rel.related_name:
-            self.rel.related_name = self.rel.related_name % {'class': cls.__name__.lower()}
 
     def set_attributes_from_rel(self):
         self.name = self.name or (self.rel.to._meta.object_name.lower() + '_' + self.rel.to._meta.pk.name)
@@ -119,7 +121,8 @@
     def do_related_class(self, other, cls):
         self.set_attributes_from_rel()
         related = RelatedObject(other, cls, self)
-        self.contribute_to_related_class(other, related)
+        if not cls._meta.abstract:
+            self.contribute_to_related_class(other, related)
 
     def get_db_prep_lookup(self, lookup_type, value):
         # If we are doing a lookup on a Related Field, we must be
Index: tests/modeltests/model_inheritance/models.py
===================================================================
--- tests/modeltests/model_inheritance/models.py	(revision 7523)
+++ tests/modeltests/model_inheritance/models.py	(working copy)
@@ -39,6 +39,29 @@
         pass
 
 #
+# Abstract base classes with related models
+#
+
+class Post(models.Model):
+    title = models.CharField(max_length=50)
+
+class Attachment(models.Model):
+    post = models.ForeignKey(Post, related_name='attached_%(class)s_set')
+    content = models.TextField()
+
+    class Meta:
+        abstract = True
+
+    def __unicode__(self):
+        return self.content
+
+class Comment(Attachment):
+    is_spam = models.BooleanField()
+
+class Link(Attachment):
+    url = models.URLField()
+
+#
 # Multi-table inheritance
 #
 
@@ -128,6 +151,22 @@
     ...
 AttributeError: type object 'CommonInfo' has no attribute 'objects'
 
+# Create a Post
+>>> post = Post(title='Lorem Ipsum')
+>>> post.save()
+
+# The Post model should have accessors for the Comment and Link models
+>>> post.attached_comment_set.create(content='Save $ on V1agr@', is_spam=True)
+<Comment: Save $ on V1agr@>
+>>> post.attached_link_set.create(content='The Web framework for perfectionists with deadlines.', url='http://www.djangoproject.com/')
+<Link: The Web framework for perfectionists with deadlines.>
+
+# The Post model should not have an attribute 'attached_%(class)s_set'
+>>> getattr(post, 'attached_%(class)s_set')
+Traceback (most recent call last):
+    ...
+AttributeError: 'Post' object has no attribute 'attached_%(class)s_set'
+
 # The Place/Restaurant/ItalianRestaurant models, on the other hand, all exist
 # as independent models. However, the subclasses also have transparent access
 # to the fields of their ancestors.
