Index: tests/regressiontests/inspectdb/tests.py
===================================================================
--- tests/regressiontests/inspectdb/tests.py	(wersja 16156)
+++ tests/regressiontests/inspectdb/tests.py	(kopia robocza)
@@ -14,3 +14,15 @@
         self.assertNotIn("from = models.ForeignKey(InspectdbPeople)", out.getvalue(), msg=error_message)
         self.assertIn("from_field = models.ForeignKey(InspectdbPeople)", out.getvalue())
         out.close()
+
+    @skipUnlessDBFeature('can_introspect_foreign_keys')
+    def test_similar_attribute_names(self):
+        out = StringIO()
+        call_command('inspectdb', stdout=out)
+        self.assertNotIn("__field = models.IntegerField(db_column='_field')", out.getvalue())
+        self.assertNotIn("Field_ = models.IntegerField(db_column='Field_')", out.getvalue())
+        self.assertNotIn("Field__ = models.IntegerField(db_column='Field_')", out.getvalue())
+        self.assertIn("field = models.IntegerField()", out.getvalue())
+        self.assertIn("field_field = models.IntegerField(db_column='Field_')", out.getvalue())
+        self.assertIn("field_field_0 = models.IntegerField(db_column='Field__')", out.getvalue())
+        self.assertIn("field_field_1 = models.IntegerField(db_column='__field')", out.getvalue())
Index: tests/regressiontests/inspectdb/models.py
===================================================================
--- tests/regressiontests/inspectdb/models.py	(wersja 16156)
+++ tests/regressiontests/inspectdb/models.py	(kopia robocza)
@@ -6,3 +6,11 @@
 
 class Message(models.Model):
     from_field = models.ForeignKey(People, db_column='from_id')
+
+class ColumnNames(models.Model):
+    valid_name = models.IntegerField(db_column='valid_name')
+
+    field = models.IntegerField(db_column='field')
+    field_field_0 = models.IntegerField(db_column='Field_')
+    field_field_1 = models.IntegerField(db_column='Field__')
+    field_field_2 = models.IntegerField(db_column='__field')
Index: django/core/management/commands/inspectdb.py
===================================================================
--- django/core/management/commands/inspectdb.py	(wersja 16156)
+++ django/core/management/commands/inspectdb.py	(kopia robocza)
@@ -1,4 +1,6 @@
 import keyword
+import re
+from itertools import count
 from optparse import make_option
 
 from django.core.management.base import NoArgsCommand, CommandError
@@ -51,28 +53,53 @@
                 indexes = connection.introspection.get_indexes(cursor, table_name)
             except NotImplementedError:
                 indexes = {}
+            used_column_names = [] # Holds column names used in the table so far.
             for i, row in enumerate(connection.introspection.get_table_description(cursor, table_name)):
                 column_name = row[0]
                 att_name = column_name.lower()
                 comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
                 extra_params = {}  # Holds Field parameters such as 'db_column'.
+                invalid_name_re = re.compile(r'([^a-zA-Z0-9_])') # Determines whether att_name is a valid Python name or not.
 
-                # If the column name can't be used verbatim as a Python
-                # attribute, set the "db_column" for this Field.
-                if ' ' in att_name or '-' in att_name or keyword.iskeyword(att_name) or column_name != att_name:
-                    extra_params['db_column'] = column_name
-
                 # Modify the field name to make it Python-compatible.
-                if ' ' in att_name:
-                    att_name = att_name.replace(' ', '_')
-                    comment_notes.append('Field renamed to remove spaces.')
-                    
-                if '-' in att_name:
-                    att_name = att_name.replace('-', '_')
-                    comment_notes.append('Field renamed to remove dashes.')
-                    
+                invalid_chars = invalid_name_re.findall(att_name)
+                if invalid_chars:
+                    for char in invalid_chars:
+                        att_name = att_name.replace(char, '_')
+                    comment_notes.append('Field renamed to remove characters "%s".' % invalid_chars)
+                if att_name.startswith('_'):
+                    att_name = 'field' + att_name
+                    comment_notes.append('Field renamed because it started with "_".')
+                if att_name.endswith('_'):
+                    att_name += 'field'
+                    comment_notes.append('Field renamed because it ended with "_".')
+                if att_name[0].isdigit():
+                    att_name = 'field_' + att_name
+                    comment_notes.append('Field renamed because it started with a digit.')
+                if keyword.iskeyword(att_name):
+                    att_name += '_field'
+                    comment_notes.append('Field renamed because it was a Python reserved word.')
+                if att_name.find('__') >= 0:
+                    while att_name.find('__') >= 0:
+                        att_name = att_name.replace('__', '_')
+                    comment_notes.append('Field renamed because it contained more than one "_" in a row.')
+                   
                 if column_name != att_name:
+                    # If this column name was already used, find another one.
+                    if att_name in used_column_names:
+                        for num in count():
+                            tmp_name = '%s_%d' % (att_name, num)
+                            if tmp_name not in used_column_names:
+                                att_name = tmp_name
+                                break
+                    comment_notes.append('Field renamed because of name conflict')
+                    used_column_names.append(att_name)
+                    # If the column name can't be used verbatim as a Python
+                    # attribute, set the "db_column" for this Field.
+                    extra_params['db_column'] = column_name
                     comment_notes.append('Field name made lowercase.')
+                else:
+                    used_column_names.append(att_name)
 
                 if i in relations:
                     rel_to = relations[i][1] == table_name and "'self'" or table2model(relations[i][1])
