Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #1328 -- Improved 'inspectdb' to handle Python reserved words a…

…s field names. Also updated docs.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@2271 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 9423c4e4a886b373243811e08a40a031ae484772 1 parent ee484f1
Adrian Holovaty authored February 04, 2006
2  django/core/db/backends/sqlite3.py
@@ -214,7 +214,7 @@ def __getitem__(self, key):
214 214
             import re
215 215
             m = re.search(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$', key)
216 216
             if m:
217  
-                return ('CharField', {'maxlength': m.group(1)})
  217
+                return ('CharField', {'maxlength': int(m.group(1))})
218 218
             raise KeyError
219 219
 
220 220
 DATA_TYPES_REVERSE = FlexibleFieldLookupDict()
46  django/core/management.py
@@ -5,6 +5,10 @@
5 5
 import os, re, sys, textwrap
6 6
 from optparse import OptionParser
7 7
 
  8
+# For Python 2.3
  9
+if not hasattr(__builtins__, 'set'):
  10
+    from sets import Set as set
  11
+
8 12
 MODULE_TEMPLATE = '''    {%% if perms.%(app)s.%(addperm)s or perms.%(app)s.%(changeperm)s %%}
9 13
     <tr>
10 14
         <th>{%% if perms.%(app)s.%(changeperm)s %%}<a href="%(app)s/%(mod)s/">{%% endif %%}%(name)s{%% if perms.%(app)s.%(changeperm)s %%}</a>{%% endif %%}</th>
@@ -563,6 +567,8 @@ def table2model(table_name):
563 567
         object_name = table_name.title().replace('_', '')
564 568
         return object_name.endswith('s') and object_name[:-1] or object_name
565 569
 
  570
+    reserved_python_words = set(['and', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while'])
  571
+
566 572
     settings.DATABASE_NAME = db_name
567 573
     cursor = db.db.cursor()
568 574
     yield "# This is an auto-generated Django model module."
@@ -584,37 +590,47 @@ def table2model(table_name):
584 590
             relations = {}
585 591
         for i, row in enumerate(db.get_table_description(cursor, table_name)):
586 592
             column_name = row[0]
  593
+            comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
  594
+            extra_params = {}  # Holds Field parameters such as 'db_column'.
  595
+
  596
+            if column_name in reserved_python_words:
  597
+                extra_params['db_column'] = column_name
  598
+                column_name += '_field'
  599
+                comment_notes.append('Field renamed because it was a Python reserved word.')
  600
+
587 601
             if relations.has_key(i):
588  
-                rel = relations[i]
589  
-                rel_to = rel[1] == table_name and "'self'" or table2model(rel[1])
  602
+                rel_to = relations[i][1] == table_name and "'self'" or table2model(relations[i][1])
  603
+                field_type = 'ForeignKey(%s' % rel_to
590 604
                 if column_name.endswith('_id'):
591  
-                    field_desc = '%s = meta.ForeignKey(%s' % (column_name[:-3], rel_to)
  605
+                    column_name = column_name[:-3]
592 606
                 else:
593  
-                    field_desc = '%s = meta.ForeignKey(%s, db_column=%r' % (column_name, rel_to, column_name)
  607
+                    extra_params['db_column'] = column_name
594 608
             else:
595 609
                 try:
596 610
                     field_type = db.DATA_TYPES_REVERSE[row[1]]
597 611
                 except KeyError:
598 612
                     field_type = 'TextField'
599  
-                    field_type_was_guessed = True
600  
-                else:
601  
-                    field_type_was_guessed = False
  613
+                    comment_notes.append('This field type is a guess.')
602 614
 
603 615
                 # This is a hook for DATA_TYPES_REVERSE to return a tuple of
604 616
                 # (field_type, extra_params_dict).
605 617
                 if type(field_type) is tuple:
606  
-                    field_type, extra_params = field_type
607  
-                else:
608  
-                    extra_params = {}
  618
+                    field_type, new_params = field_type
  619
+                    extra_params.update(new_params)
609 620
 
610 621
                 if field_type == 'CharField' and row[3]:
611 622
                     extra_params['maxlength'] = row[3]
612 623
 
613  
-                field_desc = '%s = meta.%s(' % (column_name, field_type)
614  
-                field_desc += ', '.join(['%s=%s' % (k, v) for k, v in extra_params.items()])
615  
-                field_desc += ')'
616  
-                if field_type_was_guessed:
617  
-                    field_desc += ' # This is a guess!'
  624
+                field_type += '('
  625
+
  626
+            field_desc = '%s = meta.%s' % (column_name, field_type)
  627
+            if extra_params:
  628
+                if not field_desc.endswith('('):
  629
+                    field_desc += ', '
  630
+                field_desc += ', '.join(['%s=%r' % (k, v) for k, v in extra_params.items()])
  631
+            field_desc += ')'
  632
+            if comment_notes:
  633
+                field_desc += ' # ' + ' '.join(comment_notes)
618 634
             yield '    %s' % field_desc
619 635
         yield '    class META:'
620 636
         yield '        db_table = %r' % table_name
18  docs/django-admin.txt
@@ -92,6 +92,24 @@ Use this if you have a legacy database with which you'd like to use Django.
92 92
 The script will inspect the database and create a model for each table within
93 93
 it.
94 94
 
  95
+As you might expect, the created models will have an attribute for every field
  96
+in the table. Note that ``inspectdb`` has a few special cases in its field-name
  97
+output:
  98
+
  99
+    * If ``inspectdb`` cannot map a column's type to a model field type, it'll
  100
+      use ``TextField`` and will insert the Python comment
  101
+      ``'This field type is a guess.'`` next to the field in the generated
  102
+      model.
  103
+
  104
+    * **New in Django development version.** If the database column name is a
  105
+      Python reserved word (such as ``'pass'``, ``'class'`` or ``'for'``),
  106
+      ``inspectdb`` will append ``'_field'`` to the attribute name. For
  107
+      example, if a table has a column ``'for'``, the generated model will have
  108
+      a field ``'for_field'``, with the ``db_column`` attribute set to
  109
+      ``'for'``. ``inspectdb`` will insert the Python comment
  110
+      ``'Field renamed because it was a Python reserved word.'`` next to the
  111
+      field.
  112
+
95 113
 This feature is meant as a shortcut, not as definitive model generation. After
96 114
 you run it, you'll want to look over the generated models yourself to make
97 115
 customizations. In particular, you'll need to do this:

0 notes on commit 9423c4e

Please sign in to comment.
Something went wrong with that request. Please try again.