Ticket #12460: inspectdb.diff

File inspectdb.diff, 6.2 KB (added by kgibula, 13 years ago)

updated patch

  • tests/regressiontests/inspectdb/tests.py

     
    1414        self.assertNotIn("from = models.ForeignKey(InspectdbPeople)", out.getvalue(), msg=error_message)
    1515        self.assertIn("from_field = models.ForeignKey(InspectdbPeople)", out.getvalue())
    1616        out.close()
     17
     18    @skipUnlessDBFeature('can_introspect_foreign_keys')
     19    def test_similar_attribute_names(self):
     20        out = StringIO()
     21        call_command('inspectdb', stdout=out)
     22        self.assertNotIn("__field = models.IntegerField(db_column='_field')", out.getvalue())
     23        self.assertNotIn("Field_ = models.IntegerField(db_column='Field_')", out.getvalue())
     24        self.assertNotIn("Field__ = models.IntegerField(db_column='Field_')", out.getvalue())
     25        self.assertIn("field = models.IntegerField()", out.getvalue())
     26        self.assertIn("field_field = models.IntegerField(db_column='Field_')", out.getvalue())
     27        self.assertIn("field_field_0 = models.IntegerField(db_column='Field__')", out.getvalue())
     28        self.assertIn("field_field_1 = models.IntegerField(db_column='__field')", out.getvalue())
  • tests/regressiontests/inspectdb/models.py

     
    66
    77class Message(models.Model):
    88    from_field = models.ForeignKey(People, db_column='from_id')
     9
     10class ColumnNames(models.Model):
     11    valid_name = models.IntegerField(db_column='valid_name')
     12
     13    field = models.IntegerField(db_column='field')
     14    field_field_0 = models.IntegerField(db_column='Field_')
     15    field_field_1 = models.IntegerField(db_column='Field__')
     16    field_field_2 = models.IntegerField(db_column='__field')
  • django/core/management/commands/inspectdb.py

     
    11import keyword
     2import re
     3from itertools import count
    24from optparse import make_option
    35
    46from django.core.management.base import NoArgsCommand, CommandError
     
    5153                indexes = connection.introspection.get_indexes(cursor, table_name)
    5254            except NotImplementedError:
    5355                indexes = {}
     56            used_column_names = [] # Holds column names used in the table so far.
    5457            for i, row in enumerate(connection.introspection.get_table_description(cursor, table_name)):
    5558                column_name = row[0]
    5659                att_name = column_name.lower()
    5760                comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
    5861                extra_params = {}  # Holds Field parameters such as 'db_column'.
     62                invalid_name_re = re.compile(r'([^a-zA-Z0-9_])') # Determines whether att_name is a valid Python name or not.
    5963
    60                 # If the column name can't be used verbatim as a Python
    61                 # attribute, set the "db_column" for this Field.
    62                 if ' ' in att_name or '-' in att_name or keyword.iskeyword(att_name) or column_name != att_name:
    63                     extra_params['db_column'] = column_name
    64 
    6564                # Modify the field name to make it Python-compatible.
    66                 if ' ' in att_name:
    67                     att_name = att_name.replace(' ', '_')
    68                     comment_notes.append('Field renamed to remove spaces.')
    69                    
    70                 if '-' in att_name:
    71                     att_name = att_name.replace('-', '_')
    72                     comment_notes.append('Field renamed to remove dashes.')
    73                    
     65                invalid_chars = invalid_name_re.findall(att_name)
     66                if invalid_chars:
     67                    for char in invalid_chars:
     68                        att_name = att_name.replace(char, '_')
     69                    comment_notes.append('Field renamed to remove characters "%s".' % invalid_chars)
     70                if att_name.startswith('_'):
     71                    att_name = 'field' + att_name
     72                    comment_notes.append('Field renamed because it started with "_".')
     73                if att_name.endswith('_'):
     74                    att_name += 'field'
     75                    comment_notes.append('Field renamed because it ended with "_".')
     76                if att_name[0].isdigit():
     77                    att_name = 'field_' + att_name
     78                    comment_notes.append('Field renamed because it started with a digit.')
     79                if keyword.iskeyword(att_name):
     80                    att_name += '_field'
     81                    comment_notes.append('Field renamed because it was a Python reserved word.')
     82                if att_name.find('__') >= 0:
     83                    while att_name.find('__') >= 0:
     84                        att_name = att_name.replace('__', '_')
     85                    comment_notes.append('Field renamed because it contained more than one "_" in a row.')
     86                   
    7487                if column_name != att_name:
     88                    # If this column name was already used, find another one.
     89                    if att_name in used_column_names:
     90                        for num in count():
     91                            tmp_name = '%s_%d' % (att_name, num)
     92                            if tmp_name not in used_column_names:
     93                                att_name = tmp_name
     94                                break
     95                    comment_notes.append('Field renamed because of name conflict')
     96                    used_column_names.append(att_name)
     97                    # If the column name can't be used verbatim as a Python
     98                    # attribute, set the "db_column" for this Field.
     99                    extra_params['db_column'] = column_name
    75100                    comment_notes.append('Field name made lowercase.')
     101                else:
     102                    used_column_names.append(att_name)
    76103
    77104                if i in relations:
    78105                    rel_to = relations[i][1] == table_name and "'self'" or table2model(relations[i][1])
Back to Top