Index: django/db/models/fields/related.py
===================================================================
--- django/db/models/fields/related.py	(revision 14336)
+++ django/db/models/fields/related.py	(working copy)
@@ -998,6 +998,9 @@
         if kwargs['rel'].through is not None:
             assert self.db_table is None, "Cannot specify a db_table if an intermediary model is used."
 
+        self.source_fk_name = kwargs.pop('source_fk_name', None)
+        self.target_fk_name = kwargs.pop('target_fk_name', None)
+
         Field.__init__(self, **kwargs)
 
         msg = _('Hold down "Control", or "Command" on a Mac, to select more than one.')
@@ -1023,8 +1026,9 @@
             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:
-                setattr(self, cache_attr, getattr(f, attr))
-                return getattr(self, cache_attr)
+                if not self.source_fk_name or self.source_fk_name == f.name:
+                    setattr(self, cache_attr, getattr(f, attr))
+                    return getattr(self, cache_attr)
 
     def _get_m2m_reverse_attr(self, related, attr):
         "Function that can be curried to provide the related accessor or DB column name for the m2m table"
@@ -1034,7 +1038,7 @@
         found = False
         for f in self.rel.through._meta.fields:
             if hasattr(f,'rel') and f.rel and f.rel.to == related.parent_model:
-                if related.model == related.parent_model:
+                if not self.target_fk_name and related.model == related.parent_model:
                     # If this is an m2m-intermediate to self,
                     # the first foreign key you find will be
                     # the source column. Keep searching for
@@ -1044,7 +1048,7 @@
                         break
                     else:
                         found = True
-                else:
+                elif not self.target_fk_name or self.target_fk_name == f.name:
                     setattr(self, cache_attr, getattr(f, attr))
                     break
         return getattr(self, cache_attr)
Index: django/core/management/validation.py
===================================================================
--- django/core/management/validation.py	(revision 14336)
+++ django/core/management/validation.py	(working copy)
@@ -160,24 +160,27 @@
                                 )
                             )
                     else:
-                        if rel_to == from_model:
+                        if rel_to == from_model and (not getattr(f, 'source_fk_name', None) or f.source_fk_name == inter_field.name):
                             if seen_from:
                                 e.add(opts, "Intermediary model %s has more "
                                     "than one foreign key to %s, which is "
-                                    "ambiguous and is not permitted." % (
+                                    "ambiguous and is not permitted. Add an source_fk_name "
+                                    "argument to the definition for %s." % (
                                         f.rel.through._meta.object_name,
-                                         from_model._meta.object_name
+                                         from_model._meta.object_name,
+                                         f.name
                                      )
                                  )
                             else:
                                 seen_from = True
-                        elif rel_to == to_model:
+                        elif rel_to == to_model and (not getattr(f, 'target_fk_name', None) or f.target_fk_name == inter_field.name):
                             if seen_to:
                                 e.add(opts, "Intermediary model %s has more "
-                                    "than one foreign key to %s, which is "
-                                    "ambiguous and is not permitted." % (
+                                    "than one foreign key to %s. Add a target_fk_name "
+                                    "argument to the definition for %s." % (
                                         f.rel.through._meta.object_name,
-                                        rel_to._meta.object_name
+                                        rel_to._meta.object_name,
+                                        f.name
                                     )
                                 )
                             else:
Index: docs/topics/db/models.txt
===================================================================
--- docs/topics/db/models.txt	(revision 14336)
+++ docs/topics/db/models.txt	(working copy)
@@ -433,13 +433,17 @@
 
 There are a few restrictions on the intermediate model:
 
-    * Your intermediate model must contain one - and *only* one - foreign key
-      to the target model (this would be ``Person`` in our example). If you
-      have more than one foreign key, a validation error will be raised.
+    * To automatically detect the target foreign key, your intermediate model
+      must contain one - and *only* one - foreign key to the target model (this
+      would be ``Person`` in our example). If you have more than one foreign
+      key, you will need to specify the field name by specifying a
+      :attr:`~django.db.models.ManyToManyField.target_fk_name`.
 
-    * Your intermediate model must contain one - and *only* one - foreign key
-      to the source model (this would be ``Group`` in our example). If you
-      have more than one foreign key, a validation error will be raised.
+    * To automatically detect the source foreign key, your intermediate model
+      must contain one - and *only* one - foreign key to the source model (this
+      would be ``Group`` in our example). If you have more than one foreign key,
+      you will need to specify the field name by specifying a
+      :attr:`~django.db.models.ManyToManyField.source_fk_name`.
 
     * The only exception to this is a model which has a many-to-many
       relationship to itself, through an intermediary model. In this
