diff -r bbd9e2300e50 django/db/backends/mysql/introspection.py
--- a/django/db/backends/mysql/introspection.py	Wed Jan 11 10:19:05 2012 +0000
+++ b/django/db/backends/mysql/introspection.py	Thu Jan 12 21:57:55 2012 +0100
@@ -107,6 +107,9 @@
         cursor.execute("SHOW INDEX FROM %s" % self.connection.ops.quote_name(table_name))
         indexes = {}
         for row in cursor.fetchall():
-            indexes[row[4]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1])}
+            if row[2] in indexes:
+                indexes[row[2]]['fields'].append(row[4])
+            else:
+                indexes[row[2]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1]), 'fields': [row[4]]}
         return indexes
 
diff -r bbd9e2300e50 django/db/backends/postgresql_psycopg2/introspection.py
--- a/django/db/backends/postgresql_psycopg2/introspection.py	Wed Jan 11 10:19:05 2012 +0000
+++ b/django/db/backends/postgresql_psycopg2/introspection.py	Thu Jan 12 21:57:55 2012 +0100
@@ -20,7 +20,7 @@
         1266: 'TimeField',
         1700: 'DecimalField',
     }
-        
+
     def get_table_list(self, cursor):
         "Returns a list of table names in the current database."
         cursor.execute("""
@@ -65,21 +65,18 @@
         # This query retrieves each index on the given table, including the
         # first associated field name
         cursor.execute("""
-            SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary
+            SELECT c2.relname, attr.attname, idx.indisunique, idx.indisprimary
             FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
                 pg_catalog.pg_index idx, pg_catalog.pg_attribute attr
             WHERE c.oid = idx.indrelid
                 AND idx.indexrelid = c2.oid
                 AND attr.attrelid = c.oid
-                AND attr.attnum = idx.indkey[0]
+                AND attr.attnum = ANY (idx.indkey)
                 AND c.relname = %s""", [table_name])
         indexes = {}
         for row in cursor.fetchall():
-            # row[1] (idx.indkey) is stored in the DB as an array. It comes out as
-            # a string of space-separated integers. This designates the field
-            # indexes (1-based) of the fields that have indexes on the table.
-            # Here, we skip any indexes across multiple fields.
-            if ' ' in row[1]:
-                continue
-            indexes[row[0]] = {'primary_key': row[3], 'unique': row[2]}
+            if row[0] in indexes:
+                indexes[row[0]]['fields'].append(row[1])
+            else:
+                indexes[row[0]] = {'primary_key': row[3], 'unique': row[2], 'fields': [row[1]]}
         return indexes
diff -r bbd9e2300e50 django/db/backends/sqlite3/introspection.py
--- a/django/db/backends/sqlite3/introspection.py	Wed Jan 11 10:19:05 2012 +0000
+++ b/django/db/backends/sqlite3/introspection.py	Thu Jan 12 21:57:55 2012 +0100
@@ -140,21 +140,20 @@
              'unique': boolean representing whether it's a unique index}
         """
         indexes = {}
+        primaries = []
         for info in self._table_info(cursor, table_name):
-            indexes[info['name']] = {'primary_key': info['pk'] != 0,
-                                     'unique': False}
+            if info['pk'] != 0:
+                primaries.append(info['name'])
+        indexes['_'.join(primaries)] = {'primary_key': True, 'unique': False, 'fields': primaries}
+
         cursor.execute('PRAGMA index_list(%s)' % self.connection.ops.quote_name(table_name))
         # seq, name, unique
         for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]:
-            if not unique:
-                continue
             cursor.execute('PRAGMA index_info(%s)' % self.connection.ops.quote_name(index))
             info = cursor.fetchall()
-            # Skip indexes across multiple fields
-            if len(info) != 1:
-                continue
-            name = info[0][2] # seqno, cid, name
-            indexes[name]['unique'] = True
+            name = index
+            fields = [row[2] for row in info]  # seqno, cid, name
+            indexes[name] = {'primary_key': False, 'unique': bool(unique), 'fields': fields}
         return indexes
 
     def get_primary_key_column(self, cursor, table_name):
