Index: django/db/models/fields/related.py
===================================================================
--- django/db/models/fields/related.py	(revision 4692)
+++ django/db/models/fields/related.py	(working copy)
@@ -6,6 +6,7 @@
 from django.utils.translation import gettext_lazy, string_concat, ngettext
 from django.utils.functional import curry
 from django.core import validators
+from django.core.exceptions import ImproperlyConfigured
 from django import oldforms
 from django import newforms as forms
 from django.dispatch import dispatcher
@@ -23,11 +24,21 @@
 
 def add_lookup(rel_cls, field):
     name = field.rel.to
-    module = rel_cls.__module__
-    key = (module, name)
+    # name should be either the name of a model in the same application or the
+    # name of a model in another application referenced with standard Django
+    # dotted notation ('appname.modelname')
+    if name.find('.') is -1:
+        app_name = rel_cls._meta.app_label
+        model_name = name
+    else:
+        try:
+            app_name, model_name = name.split('.')
+        except ValueError:
+            raise ImproperlyConfigured, "Invalid definition for field %s (%s). Please use app_name.model_name notation." % (field.name, name)
+    key = (app_name, model_name)
     # Has the model already been loaded?
     # If so, resolve the string reference right away
-    model = get_model(rel_cls._meta.app_label, field.rel.to, False)
+    model = get_model(app_name, model_name, False)
     if model:
         field.rel.to = model
         field.do_related_class(model, rel_cls)
@@ -37,7 +48,7 @@
 
 def do_pending_lookups(sender):
     other_cls = sender
-    key = (other_cls.__module__, other_cls.__name__)
+    key = (other_cls._meta.app_label, other_cls.__name__)
     for rel_cls, field in pending_lookups.setdefault(key, []):
         field.rel.to = other_cls
         field.do_related_class(other_cls, rel_cls)
Index: docs/model-api.txt
===================================================================
--- docs/model-api.txt	(revision 4692)
+++ docs/model-api.txt	(working copy)
@@ -682,23 +682,9 @@
         manufacturer = models.ForeignKey(Manufacturer)
         # ...
 
-To create a recursive relationship -- an object that has a many-to-one
-relationship with itself -- use ``models.ForeignKey('self')``.
+For information on establishing relationships to ``self``, and as-of-yet
+undefined models, see `recursive relationships`_ below.
 
-If you need to create a relationship on a model that has not yet been defined,
-you can use the name of the model, rather than the model object itself::
-
-    class Car(models.Model):
-        manufacturer = models.ForeignKey('Manufacturer')
-        # ...
-
-    class Manufacturer(models.Model):
-        # ...
-
-Note, however, that you can only use strings to refer to models in the same
-models.py file -- you cannot use a string to reference a model in a different
-application, or to reference a model that has been imported from elsewhere.
-
 Behind the scenes, Django appends ``"_id"`` to the field name to create its
 database column name. In the above example, the database table for the ``Car``
 model will have a ``manufacturer_id`` column. (You can change this explicitly
@@ -817,13 +803,9 @@
         # ...
         toppings = models.ManyToManyField(Topping)
 
-As with ``ForeignKey``, a relationship to self can be defined by using the
-string ``'self'`` instead of the model name, and you can refer to as-yet
-undefined models by using a string containing the model name. However, you
-can only use strings to refer to models in the same models.py file -- you
-cannot use a string to reference a model in a different application, or to
-reference a model that has been imported from elsewhere.
-
+For information on establishing relationships to ``self``, and as-of-yet
+undefined models, see `recursive relationships`_ below.
+		
 It's suggested, but not required, that the name of a ``ManyToManyField``
 (``toppings`` in the example above) be a plural describing the set of related
 model objects.
@@ -910,9 +892,8 @@
 could make ``Restaurant`` have a ``OneToOneField`` to ``Place`` (because a
 restaurant "is-a" place).
 
-As with ``ForeignKey``, a relationship to self can be defined by using the
-string ``"self"`` instead of the model name; references to as-yet undefined
-models can be made by using a string containing the model name.
+For information on establishing relationships to as-of-yet undefined models,
+see `recursive relationships`_ below.
 
 This ``OneToOneField`` will actually replace the primary key ``id`` field
 (since one-to-one relations share the same primary key), and will be displayed
@@ -922,6 +903,58 @@
 
 .. _One-to-one relationship model example: http://www.djangoproject.com/documentation/models/one_to_one/
 
+Recursive relationships
+~~~~~~~~~~~~~~~~~~~~~~~
+To create a recursive relationship -- an object that has a many-to-one
+relationship with itself -- use ``models.ForeignKey('self')`` or
+``models.ManyToMany('self')``
+
+If you need to create a relationship on a model that has not yet been defined,
+you can use the name of the model, rather than the model object itself::
+
+    class Car(models.Model):
+        manufacturer = models.ForeignKey('Manufacturer')
+        # ...
+
+    class Manufacturer(models.Model):
+        # ...
+
+Note, however, that you can only use strings to refer to models in the same
+models.py file -- you cannot use a string to reference a model in a different
+application, or to reference a model that has been imported from elsewhere.
+
+**New in Django development version:** String-based references have been
+expanded to allow reference to models in other models.py files.  This usage
+provides a mechanism for enabling recursive relationships between
+tightly-coupled objects that logically reside in different applications.
+
+For example, consider a user class and a series of articles::
+
+	class User(models.Model):
+		saved_articles = models.ManyToManyField('Article')
+		# ...
+
+	class Article(models.Model):
+		author = models.ForeignKey(User)
+		# ...
+
+It doesn't make much sense for users and articles to be stored in the same
+models.py file.  By using dotted-notation (``app_name.model_name``), it is
+possible to reference across models.py files when recursive ``import``
+statements would otherwise cause problems.
+
+my_project/accounts/models.py::
+
+	class User(models.Model):
+		saved_articles = models.ManyToManyField('articles.Article')
+		# ...
+
+my_project/articles/models.py::
+
+	class Article(models.Model):
+		author = models.ForeignKey('accounts.User')
+		# ...
+
 Meta options
 ============
 
