Ticket #3163: create_db_schema-trunk6977.diff
File create_db_schema-trunk6977.diff, 13.4 KB (added by , 17 years ago) |
---|
-
django/db/models/options.py
15 15 16 16 DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering', 17 17 'unique_together', 'permissions', 'get_latest_by', 18 'order_with_respect_to', 'app_label', 'db_tablespace' )18 'order_with_respect_to', 'app_label', 'db_tablespace', 'create_db_schema') 19 19 20 20 class Options(object): 21 21 def __init__(self, meta): … … 30 30 self.get_latest_by = None 31 31 self.order_with_respect_to = None 32 32 self.db_tablespace = settings.DEFAULT_TABLESPACE 33 self.create_db_schema = True 33 34 self.admin = None 34 35 self.meta = meta 35 36 self.pk = None -
django/core/management/sql.py
13 13 cursor = connection.cursor() 14 14 return get_introspection_module().get_table_list(cursor) 15 15 16 def django_table_list(only_existing=False ):16 def django_table_list(only_existing=False, filter_not_generated_tables=False): 17 17 """ 18 18 Returns a list of all table names that have associated Django models and 19 19 are in INSTALLED_APPS. 20 20 21 21 If only_existing is True, the resulting list will only include the tables 22 22 that actually exist in the database. 23 24 If filter_not_generated_tables is True, then all tables with associated Django models 25 which have Meta option create_db_schema=False will not be added to the list. 23 26 """ 24 27 from django.db import models 25 28 tables = [] 26 29 for app in models.get_apps(): 27 30 for model in models.get_models(app): 28 tables.append(model._meta.db_table) 29 tables.extend([f.m2m_db_table() for f in model._meta.many_to_many]) 31 if (not filter_not_generated_tables) or (model._meta.create_db_schema): 32 tables.append(model._meta.db_table) 33 tables.extend([f.m2m_db_table() for f in model._meta.many_to_many]) 30 34 if only_existing: 31 35 existing = table_list() 32 36 tables = [t for t in tables if t in existing] … … 45 49 converter = lambda x: x 46 50 return set([m for m in all_models if converter(m._meta.db_table) in map(converter, table_list)]) 47 51 48 def sequence_list(): 49 "Returns a list of information about all DB sequences for all models in all apps." 52 def sequence_list(filter_not_generated_tables=False): 53 """ 54 Returns a list of information about all DB sequences for all models in all apps. 55 56 If filter_not_generated_tables is True, then only the sequences for the Django models 57 which have Meta option create_db_schema=False will be added to the list. 58 """ 50 59 from django.db import models 51 60 52 61 apps = models.get_apps() … … 54 63 55 64 for app in apps: 56 65 for model in models.get_models(app): 57 for f in model._meta.fields: 58 if isinstance(f, models.AutoField): 59 sequence_list.append({'table': model._meta.db_table, 'column': f.column}) 60 break # Only one AutoField is allowed per model, so don't bother continuing. 66 if (not filter_not_generated_tables) or (model._meta.create_db_schema): 67 for f in model._meta.fields: 68 if isinstance(f, models.AutoField): 69 sequence_list.append({'table': model._meta.db_table, 'column': f.column}) 70 break # Only one AutoField is allowed per model, so don't bother continuing. 61 71 62 72 for f in model._meta.many_to_many: 63 73 sequence_list.append({'table': f.m2m_db_table(), 'column': None}) … … 156 166 for model in app_models: 157 167 if cursor and table_name_converter(model._meta.db_table) in table_names: 158 168 # Drop the table now 159 output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), 160 style.SQL_TABLE(qn(model._meta.db_table)))) 169 if model._meta.create_db_schema: 170 output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), 171 style.SQL_TABLE(qn(model._meta.db_table)))) 161 172 if connection.features.supports_constraints and model in references_to_delete: 162 173 for rel_class, f in references_to_delete[model]: 163 174 table = rel_class._meta.db_table … … 165 176 r_table = model._meta.db_table 166 177 r_col = model._meta.get_field(f.rel.field_name).column 167 178 r_name = '%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table)))) 168 output.append('%s %s %s %s;' % \ 169 (style.SQL_KEYWORD('ALTER TABLE'), 170 style.SQL_TABLE(qn(table)), 171 style.SQL_KEYWORD(connection.ops.drop_foreignkey_sql()), 172 style.SQL_FIELD(truncate_name(r_name, connection.ops.max_name_length())))) 179 if rel_class._meta.create_db_schema: 180 output.append('%s %s %s %s;' % \ 181 (style.SQL_KEYWORD('ALTER TABLE'), 182 style.SQL_TABLE(qn(table)), 183 style.SQL_KEYWORD(connection.ops.drop_foreignkey_sql()), 184 style.SQL_FIELD(truncate_name(r_name, connection.ops.max_name_length())))) 173 185 del references_to_delete[model] 174 186 if model._meta.has_auto_field: 175 187 ds = connection.ops.drop_sequence_sql(model._meta.db_table) … … 206 218 def sql_flush(style, only_django=False): 207 219 """ 208 220 Returns a list of the SQL statements used to flush the database. 209 221 210 222 If only_django is True, then only table names that have associated Django 211 223 models and are in INSTALLED_APPS will be included. 212 224 """ 213 225 from django.db import connection 214 226 if only_django: 215 tables = django_table_list( )227 tables = django_table_list(filter_not_generated_tables=True) 216 228 else: 217 229 tables = table_list() 218 statements = connection.ops.sql_flush(style, tables, sequence_list( ))230 statements = connection.ops.sql_flush(style, tables, sequence_list(filter_not_generated_tables=True)) 219 231 return statements 220 232 221 233 def sql_custom(app): … … 295 307 table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \ 296 308 ", ".join([qn(style.SQL_FIELD(opts.get_field(f).column)) for f in field_constraints])) 297 309 298 full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(qn(opts.db_table)) + ' ('] 299 for i, line in enumerate(table_output): # Combine and add commas. 300 full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) 301 full_statement.append(')') 302 if opts.db_tablespace and connection.features.supports_tablespaces: 303 full_statement.append(connection.ops.tablespace_sql(opts.db_tablespace)) 304 full_statement.append(';') 305 final_output.append('\n'.join(full_statement)) 310 # Now build up the CREATE TABLE section but only if the model requires it 311 if opts.create_db_schema: 312 full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(qn(opts.db_table)) + ' ('] 313 for i, line in enumerate(table_output): # Combine and add commas. 314 full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) 315 full_statement.append(')') 316 if opts.db_tablespace and connection.features.supports_tablespaces: 317 full_statement.append(connection.ops.tablespace_sql(opts.db_tablespace)) 318 full_statement.append(';') 319 final_output.append('\n'.join(full_statement)) 306 320 307 if opts.has_auto_field:308 # Add any extra SQL needed to support auto-incrementing primary keys.309 auto_column = opts.auto_field.db_column or opts.auto_field.name310 autoinc_sql = connection.ops.autoinc_sql(opts.db_table, auto_column)311 if autoinc_sql:312 for stmt in autoinc_sql:313 final_output.append(stmt)321 if opts.has_auto_field: 322 # Add any extra SQL needed to support auto-incrementing primary keys. 323 auto_column = opts.auto_field.db_column or opts.auto_field.name 324 autoinc_sql = connection.ops.autoinc_sql(opts.db_table, auto_column) 325 if autoinc_sql: 326 for stmt in autoinc_sql: 327 final_output.append(stmt) 314 328 315 329 return final_output, pending_references 316 330 … … 335 349 # For MySQL, r_name must be unique in the first 64 characters. 336 350 # So we are careful with character usage here. 337 351 r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table)))) 338 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \ 339 (qn(r_table), truncate_name(r_name, connection.ops.max_name_length()), 340 qn(r_col), qn(table), qn(col), 341 connection.ops.deferrable_sql())) 352 if rel_opts.create_db_schema: 353 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \ 354 (qn(r_table), truncate_name(r_name, connection.ops.max_name_length()), 355 qn(r_col), qn(table), qn(col), 356 connection.ops.deferrable_sql())) 342 357 del pending_references[model] 343 358 return final_output 344 359 … … 411 426 for r_table, r_col, table, col in deferred: 412 427 r_name = '%s_refs_%s_%x' % (r_col, col, 413 428 abs(hash((r_table, table)))) 414 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % 429 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % 415 430 (qn(r_table), 416 431 truncate_name(r_name, connection.ops.max_name_length()), 417 432 qn(r_col), qn(table), qn(col), … … 458 473 output = [] 459 474 460 475 qn = connection.ops.quote_name 461 for f in model._meta.fields: 462 if f.db_index and not ((f.primary_key or f.unique) and connection.features.autoindexes_primary_keys): 463 unique = f.unique and 'UNIQUE ' or '' 464 tablespace = f.db_tablespace or model._meta.db_tablespace 465 if tablespace and connection.features.supports_tablespaces: 466 tablespace_sql = ' ' + connection.ops.tablespace_sql(tablespace) 467 else: 468 tablespace_sql = '' 469 output.append( 470 style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \ 471 style.SQL_TABLE(qn('%s_%s' % (model._meta.db_table, f.column))) + ' ' + \ 472 style.SQL_KEYWORD('ON') + ' ' + \ 473 style.SQL_TABLE(qn(model._meta.db_table)) + ' ' + \ 474 "(%s)" % style.SQL_FIELD(qn(f.column)) + \ 475 "%s;" % tablespace_sql 476 ) 476 if model._meta.create_db_schema: 477 for f in model._meta.fields: 478 if f.db_index and not ((f.primary_key or f.unique) and connection.features.autoindexes_primary_keys): 479 unique = f.unique and 'UNIQUE ' or '' 480 tablespace = f.db_tablespace or model._meta.db_tablespace 481 if tablespace and connection.features.supports_tablespaces: 482 tablespace_sql = ' ' + connection.ops.tablespace_sql(tablespace) 483 else: 484 tablespace_sql = '' 485 output.append( 486 style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \ 487 style.SQL_TABLE(qn('%s_%s' % (model._meta.db_table, f.column))) + ' ' + \ 488 style.SQL_KEYWORD('ON') + ' ' + \ 489 style.SQL_TABLE(qn(model._meta.db_table)) + ' ' + \ 490 "(%s)" % style.SQL_FIELD(qn(f.column)) + \ 491 "%s;" % tablespace_sql 492 ) 477 493 return output 478 494 479 495 def emit_post_sync_signal(created_models, verbosity, interactive): -
docs/model-api.txt
1051 1051 that aren't allowed in Python variable names -- notably, the hyphen -- 1052 1052 that's OK. Django quotes column and table names behind the scenes. 1053 1053 1054 ``create_db_schema`` 1055 -------------------- 1056 1057 **New in Django development version** 1058 1059 Marks this model as requiring SQL operations when calling ``manage.py``:: 1060 1061 create_db_schema = False 1062 1063 If this isn't given, Django will use ``create_db_schema = True`` 1064 what means that the operations like ``manage.py sqlreset``, ``manage.py syncdb`` 1065 and others will regenerate the appropriate table when needed. 1066 If the option is set to False, the appropriate table will not be affected with 1067 any SQL operations. 1068 1069 This is useful for databases where some DB tables are controlled by Django models, 1070 but some other DB tables and views are created via raw SQL and should not be affected 1071 by any ``manage.py`` actions. 1072 Note that if the initial SQL data is provided (see `Providing initial SQL 1073 data`_ below), it still will be present in the output of 1074 ``sqlall``/``sqlcustom`` commands. 1075 1054 1076 ``db_tablespace`` 1055 1077 ----------------- 1056 1078