Index: django/core/management.py
===================================================================
--- django/core/management.py	(revision 4464)
+++ django/core/management.py	(working copy)
@@ -112,11 +112,9 @@
         final_output.extend(_get_sql_for_pending_references(model, pending_references))
         # Keep track of the fact that we've created the table for this model.
         known_models.add(model)
+        # Create the many-to-many join tables.
+        final_output.extend(_get_many_to_many_sql_for_model(model,known_models,pending_references))
 
-    # Create the many-to-many join tables.
-    for model in app_models:
-        final_output.extend(_get_many_to_many_sql_for_model(model))
-
     # Handle references to tables that are from other apps
     # but don't exist physically
     not_installed_models = set(pending_references.keys())
@@ -145,6 +143,7 @@
     opts = model._meta
     final_output = []
     table_output = []
+    constraints = []
     pending_references = {}
     for f in opts.fields:
         if isinstance(f, (models.ForeignKey, models.OneToOneField)):
@@ -165,10 +164,13 @@
                 field_output.append(style.SQL_KEYWORD('PRIMARY KEY'))
             if f.rel:
                 if f.rel.to in known_models:
-                    field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \
+                    ref_text=style.SQL_KEYWORD('REFERENCES') + ' ' + \
                         style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)) + ' (' + \
                         style.SQL_FIELD(backend.quote_name(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')'
-                    )
+                    field_output.append(ref_text)
+                    constraints.append('FOREIGN KEY (%s) %s' % \
+                                           (style.SQL_FIELD(backend.quote_name(f.column)),
+                                            ref_text))
                 else:
                     # We haven't yet created the table to which this field
                     # is related, so save it for later.
@@ -178,6 +180,7 @@
         table_output.append(style.SQL_FIELD(backend.quote_name('_order')) + ' ' + \
             style.SQL_COLTYPE(data_types['IntegerField']) + ' ' + \
             style.SQL_KEYWORD('NULL'))
+    table_output += constraints
     for field_constraints in opts.unique_together:
         table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \
             ", ".join([backend.quote_name(style.SQL_FIELD(opts.get_field(f).column)) for f in field_constraints]))
@@ -198,25 +201,28 @@
     data_types = get_creation_module().DATA_TYPES
 
     final_output = []
-    if backend.supports_constraints:
+    if backend.supports_constraints and model in pending_references:
         opts = model._meta
-        if model in pending_references:
-            for rel_class, f in pending_references[model]:
-                rel_opts = rel_class._meta
-                r_table = rel_opts.db_table
+        table = opts.db_table
+        for rel_class, f in pending_references[model]:
+            if type(rel_class) == dict:
+                r_table = rel_class['table']
+                r_col = rel_class['col']
+                col = opts.pk.column
+            else:
+                r_table = rel_class._meta.db_table
                 r_col = f.column
-                table = opts.db_table
                 col = opts.get_field(f.rel.field_name).column
-                # For MySQL, r_name must be unique in the first 64 characters.
-                # So we are careful with character usage here.
-                r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))
-                final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
-                    (backend.quote_name(r_table), r_name,
-                    backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col)))
-            del pending_references[model]
+            # For MySQL, r_name must be unique in the first 64 characters.
+            # So we are careful with character usage here.
+            r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))
+            final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
+                (backend.quote_name(r_table), r_name,
+                backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col)))
+        del pending_references[model]
     return final_output
 
-def _get_many_to_many_sql_for_model(model):
+def _get_many_to_many_sql_for_model(model,known_models,pending_references):
     from django.db import backend, get_creation_module
     from django.db.models import GenericRel
 
@@ -224,6 +230,7 @@
 
     opts = model._meta
     final_output = []
+
     for f in opts.many_to_many:
         if not isinstance(f.rel, GenericRel):
             table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \
@@ -244,6 +251,18 @@
                 style.SQL_KEYWORD('NOT NULL REFERENCES'),
                 style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)),
                 style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column))))
+            table_output.append('    FOREIGN KEY (%s) REFERENCES %s (%s),' % \
+                (style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
+                style.SQL_TABLE(backend.quote_name(opts.db_table)),
+                style.SQL_FIELD(backend.quote_name(opts.pk.column))))
+            if f.rel.to in known_models:
+                table_output.append('    FOREIGN KEY (%s) REFERENCES %s (%s),' % \
+                     (style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name())),
+                      style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)),
+                      style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column))))
+            else:
+                pending_references.setdefault(f.rel.to, []).append(
+                    ({'table':f.m2m_db_table(),'col':f.m2m_reverse_name()}, f))
             table_output.append('    %s (%s, %s)' % \
                 (style.SQL_KEYWORD('UNIQUE'),
                 style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
@@ -485,16 +504,13 @@
             for statement in sql:
                 cursor.execute(statement)
             table_list.append(model._meta.db_table)
+            sql = _get_many_to_many_sql_for_model(model,seen_models,pending_references)
+            if sql:
+                if verbosity >= 2:
+                    print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name)
+                for statement in sql:
+                    cursor.execute(statement)
 
-        for model in model_list:
-            if model in created_models:
-                sql = _get_many_to_many_sql_for_model(model)
-                if sql:
-                    if verbosity >= 2:
-                        print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name)
-                    for statement in sql:
-                        cursor.execute(statement)
-
         transaction.commit_unless_managed()
 
     # Send the post_syncdb signal, so individual apps can do whatever they need
