1
0
mirror of https://github.com/django/django.git synced 2025-06-05 03:29:12 +00:00

magic-removal: Merged to [2350]

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2351 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-02-18 22:14:05 +00:00
parent 77a0a9498f
commit f594bc4445
8 changed files with 83 additions and 14 deletions

View File

@ -51,6 +51,7 @@ answer newbie questions, and generally made Django that much better:
deric@monowerks.com deric@monowerks.com
Jeremy Dunck <http://dunck.us/> Jeremy Dunck <http://dunck.us/>
Clint Ecker Clint Ecker
gandalf@owca.info
Baishampayan Ghose Baishampayan Ghose
Espen Grindhaug <http://grindhaug.org/> Espen Grindhaug <http://grindhaug.org/>
Gustavo Picon Gustavo Picon

View File

@ -752,7 +752,7 @@ def inspectdb(db_name):
yield "# This is an auto-generated Django model module." yield "# This is an auto-generated Django model module."
yield "# You'll have to do the following manually to clean this up:" yield "# You'll have to do the following manually to clean this up:"
yield "# * Rearrange models' order" yield "# * Rearrange models' order"
yield "# * Add primary_key=True to one field in each model." yield "# * Make sure each model has one field with primary_key=True"
yield "# Feel free to rename the models, but don't rename db_table values or field names." yield "# Feel free to rename the models, but don't rename db_table values or field names."
yield "#" yield "#"
yield "# Also note: You'll have to insert the output of 'django-admin.py sqlinitialdata [appname]'" yield "# Also note: You'll have to insert the output of 'django-admin.py sqlinitialdata [appname]'"
@ -766,23 +766,27 @@ def inspectdb(db_name):
relations = introspection_module.get_relations(cursor, table_name) relations = introspection_module.get_relations(cursor, table_name)
except NotImplementedError: except NotImplementedError:
relations = {} relations = {}
try:
indexes = introspection_module.get_indexes(cursor, table_name)
except NotImplementedError:
indexes = {}
for i, row in enumerate(introspection_module.get_table_description(cursor, table_name)): for i, row in enumerate(introspection_module.get_table_description(cursor, table_name)):
column_name = row[0] att_name = row[0]
comment_notes = [] # Holds Field notes, to be displayed in a Python comment. comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
extra_params = {} # Holds Field parameters such as 'db_column'. extra_params = {} # Holds Field parameters such as 'db_column'.
if keyword.iskeyword(column_name): if keyword.iskeyword(att_name):
extra_params['db_column'] = column_name extra_params['db_column'] = att_name
column_name += '_field' att_name += '_field'
comment_notes.append('Field renamed because it was a Python reserved word.') comment_notes.append('Field renamed because it was a Python reserved word.')
if relations.has_key(i): if relations.has_key(i):
rel_to = relations[i][1] == table_name and "'self'" or table2model(relations[i][1]) rel_to = relations[i][1] == table_name and "'self'" or table2model(relations[i][1])
field_type = 'ForeignKey(%s' % rel_to field_type = 'ForeignKey(%s' % rel_to
if column_name.endswith('_id'): if att_name.endswith('_id'):
column_name = column_name[:-3] att_name = att_name[:-3]
else: else:
extra_params['db_column'] = column_name extra_params['db_column'] = att_name
else: else:
try: try:
field_type = introspection_module.DATA_TYPES_REVERSE[row[1]] field_type = introspection_module.DATA_TYPES_REVERSE[row[1]]
@ -797,13 +801,26 @@ def inspectdb(db_name):
field_type, new_params = field_type field_type, new_params = field_type
extra_params.update(new_params) extra_params.update(new_params)
# Add maxlength for all CharFields.
if field_type == 'CharField' and row[3]: if field_type == 'CharField' and row[3]:
extra_params['maxlength'] = row[3] extra_params['maxlength'] = row[3]
# Add primary_key and unique, if necessary.
column_name = extra_params.get('db_column', att_name)
if column_name in indexes:
if indexes[column_name]['primary_key']:
extra_params['primary_key'] = True
elif indexes[column_name]['unique']:
extra_params['unique'] = True
field_type += '(' field_type += '('
# Don't output 'id = meta.AutoField(primary_key=True)', because
# that's assumed if it doesn't exist.
if att_name == 'id' and field_type == 'AutoField(' and extra_params == {'primary_key': True}:
continue
field_desc = '%s = models.%s' % (column_name, field_type) field_desc = '%s = models.%s' % (att_name, field_type)
if extra_params: if extra_params:
if not field_desc.endswith('('): if not field_desc.endswith('('):
field_desc += ', ' field_desc += ', '

View File

@ -7,4 +7,7 @@ def get_table_description(cursor, table_name):
def get_relations(cursor, table_name): def get_relations(cursor, table_name):
raise NotImplementedError raise NotImplementedError
def get_indexes(cursor, table_name):
raise NotImplementedError
DATA_TYPES_REVERSE = {} DATA_TYPES_REVERSE = {}

View File

@ -3,5 +3,6 @@ from django.db.backends.dummy.base import complain
get_table_list = complain get_table_list = complain
get_table_description = complain get_table_description = complain
get_relations = complain get_relations = complain
get_indexes = complain
DATA_TYPES_REVERSE = {} DATA_TYPES_REVERSE = {}

View File

@ -14,6 +14,19 @@ def get_table_description(cursor, table_name):
def get_relations(cursor, table_name): def get_relations(cursor, table_name):
raise NotImplementedError raise NotImplementedError
def get_indexes(cursor, table_name):
"""
Returns a dictionary of fieldname -> infodict for the given table,
where each infodict is in the format:
{'primary_key': boolean representing whether it's the primary key,
'unique': boolean representing whether it's a unique index}
"""
cursor.execute("SHOW INDEX FROM %s" % quote_name(table_name))
indexes = {}
for row in cursor.fetchall():
indexes[row[4]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1])}
return indexes
DATA_TYPES_REVERSE = { DATA_TYPES_REVERSE = {
FIELD_TYPE.BLOB: 'TextField', FIELD_TYPE.BLOB: 'TextField',
FIELD_TYPE.CHAR: 'CharField', FIELD_TYPE.CHAR: 'CharField',

View File

@ -37,6 +37,36 @@ def get_relations(cursor, table_name):
continue continue
return relations return relations
def get_indexes(cursor, table_name):
"""
Returns a dictionary of fieldname -> infodict for the given table,
where each infodict is in the format:
{'primary_key': boolean representing whether it's the primary key,
'unique': boolean representing whether it's a unique index}
"""
# Get the table description because we only have the column indexes, and we
# need the column names.
desc = get_table_description(cursor, table_name)
# This query retrieves each index on the given table.
cursor.execute("""
SELECT idx.indkey, idx.indisunique, idx.indisprimary
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
pg_catalog.pg_index idx
WHERE c.oid = idx.indrelid
AND idx.indexrelid = c2.oid
AND c.relname = %s""", [table_name])
indexes = {}
for row in cursor.fetchall():
# row[0] (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[0]:
continue
col_name = desc[int(row[0])-1][0]
indexes[col_name] = {'primary_key': row[2], 'unique': row[1]}
return indexes
# Maps type codes to Django Field types. # Maps type codes to Django Field types.
DATA_TYPES_REVERSE = { DATA_TYPES_REVERSE = {
16: 'BooleanField', 16: 'BooleanField',

View File

@ -11,6 +11,9 @@ def get_table_description(cursor, table_name):
def get_relations(cursor, table_name): def get_relations(cursor, table_name):
raise NotImplementedError raise NotImplementedError
def get_indexes(cursor, table_name):
raise NotImplementedError
# Maps SQL types to Django Field types. Some of the SQL types have multiple # Maps SQL types to Django Field types. Some of the SQL types have multiple
# entries here because SQLite allows for anything and doesn't normalize the # entries here because SQLite allows for anything and doesn't normalize the
# field type; it uses whatever was given. # field type; it uses whatever was given.

View File

@ -112,12 +112,13 @@ output:
This feature is meant as a shortcut, not as definitive model generation. After This feature is meant as a shortcut, not as definitive model generation. After
you run it, you'll want to look over the generated models yourself to make you run it, you'll want to look over the generated models yourself to make
customizations. In particular, you'll need to do this: customizations. In particular, you'll need to rearrange models' order, so that
models that refer to other models are ordered properly.
* Rearrange models' order, so that models that refer to other models are If you're using Django 0.90 or 0.91, you'll need to add ``primary_key=True`` to
ordered properly. one field in each model. In the Django development version, primary keys are
* Add ``primary_key=True`` to one field in each model. The ``inspectdb`` automatically introspected for PostgreSQL and MySQL, and Django puts in the
doesn't yet introspect primary keys. ``primary_key=True`` where needed.
``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection ``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection
only works in PostgreSQL. only works in PostgreSQL.