Ticket #3163: sql_generation_required-trunk6635.diff
File sql_generation_required-trunk6635.diff, 13.0 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', 'sql_generation_required') 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 = None 33 self.sql_generation_required = 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_if_sql_generation_not_required=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_if_sql_generation_not_required is True, then all tables with associated Django models 25 which have Meta option sql_generation_required=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_if_sql_generation_not_required) or (model._meta.sql_generation_required): 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_if_sql_generation_not_required=False): 53 """ 54 Returns a list of information about all DB sequences for all models in all apps. 55 56 If filter_if_sql_generation_not_required is True, then only the sequences for the Django models 57 which have Meta option sql_generation_required=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_if_sql_generation_not_required) or (model._meta.sql_generation_required): 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}) … … 155 165 for model in app_models: 156 166 if cursor and table_name_converter(model._meta.db_table) in table_names: 157 167 # Drop the table now 158 output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), 159 style.SQL_TABLE(qn(model._meta.db_table)))) 168 if model._meta.sql_generation_required: 169 output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), 170 style.SQL_TABLE(qn(model._meta.db_table)))) 160 171 if connection.features.supports_constraints and model in references_to_delete: 161 172 for rel_class, f in references_to_delete[model]: 162 173 table = rel_class._meta.db_table … … 164 175 r_table = model._meta.db_table 165 176 r_col = model._meta.get_field(f.rel.field_name).column 166 177 r_name = '%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table)))) 167 output.append('%s %s %s %s;' % \ 168 (style.SQL_KEYWORD('ALTER TABLE'), 169 style.SQL_TABLE(qn(table)), 170 style.SQL_KEYWORD(connection.ops.drop_foreignkey_sql()), 171 style.SQL_FIELD(truncate_name(r_name, connection.ops.max_name_length())))) 178 if rel_class._meta.sql_generation_required: 179 output.append('%s %s %s %s;' % \ 180 (style.SQL_KEYWORD('ALTER TABLE'), 181 style.SQL_TABLE(qn(table)), 182 style.SQL_KEYWORD(connection.ops.drop_foreignkey_sql()), 183 style.SQL_FIELD(truncate_name(r_name, connection.ops.max_name_length())))) 172 184 del references_to_delete[model] 173 185 if model._meta.has_auto_field: 174 186 ds = connection.ops.drop_sequence_sql(model._meta.db_table) … … 203 215 def sql_flush(style, only_django=False): 204 216 """ 205 217 Returns a list of the SQL statements used to flush the database. 206 218 207 219 If only_django is True, then only table names that have associated Django 208 220 models and are in INSTALLED_APPS will be included. 209 221 """ 210 222 from django.db import connection 211 223 if only_django: 212 tables = django_table_list( )224 tables = django_table_list(filter_if_sql_generation_not_required=True) 213 225 else: 214 226 tables = table_list() 215 statements = connection.ops.sql_flush(style, tables, sequence_list( ))227 statements = connection.ops.sql_flush(style, tables, sequence_list(filter_if_sql_generation_not_required=True)) 216 228 return statements 217 229 218 230 def sql_custom(app): … … 291 303 table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \ 292 304 ", ".join([qn(style.SQL_FIELD(opts.get_field(f).column)) for f in field_constraints])) 293 305 294 full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(qn(opts.db_table)) + ' ('] 295 for i, line in enumerate(table_output): # Combine and add commas. 296 full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) 297 full_statement.append(')') 298 if opts.db_tablespace and connection.features.supports_tablespaces: 299 full_statement.append(connection.ops.tablespace_sql(opts.db_tablespace)) 300 full_statement.append(';') 301 final_output.append('\n'.join(full_statement)) 306 # Now build up the CREATE TABLE section but only if the model requires it 307 if opts.sql_generation_required: 308 full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(qn(opts.db_table)) + ' ('] 309 for i, line in enumerate(table_output): # Combine and add commas. 310 full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) 311 full_statement.append(')') 312 if opts.db_tablespace and connection.features.supports_tablespaces: 313 full_statement.append(connection.ops.tablespace_sql(opts.db_tablespace)) 314 full_statement.append(';') 315 final_output.append('\n'.join(full_statement)) 302 316 303 if opts.has_auto_field:304 # Add any extra SQL needed to support auto-incrementing primary keys.305 auto_column = opts.auto_field.db_column or opts.auto_field.name306 autoinc_sql = connection.ops.autoinc_sql(opts.db_table, auto_column)307 if autoinc_sql:308 for stmt in autoinc_sql:309 final_output.append(stmt)317 if opts.has_auto_field: 318 # Add any extra SQL needed to support auto-incrementing primary keys. 319 auto_column = opts.auto_field.db_column or opts.auto_field.name 320 autoinc_sql = connection.ops.autoinc_sql(opts.db_table, auto_column) 321 if autoinc_sql: 322 for stmt in autoinc_sql: 323 final_output.append(stmt) 310 324 311 325 return final_output, pending_references 312 326 … … 331 345 # For MySQL, r_name must be unique in the first 64 characters. 332 346 # So we are careful with character usage here. 333 347 r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table)))) 334 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \ 335 (qn(r_table), truncate_name(r_name, connection.ops.max_name_length()), 336 qn(r_col), qn(table), qn(col), 337 connection.ops.deferrable_sql())) 348 if rel_opts.sql_generation_required: 349 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \ 350 (qn(r_table), truncate_name(r_name, connection.ops.max_name_length()), 351 qn(r_col), qn(table), qn(col), 352 connection.ops.deferrable_sql())) 338 353 del pending_references[model] 339 354 return final_output 340 355 … … 426 441 output = [] 427 442 428 443 qn = connection.ops.quote_name 429 for f in model._meta.fields: 430 if f.db_index and not ((f.primary_key or f.unique) and connection.features.autoindexes_primary_keys): 431 unique = f.unique and 'UNIQUE ' or '' 432 tablespace = f.db_tablespace or model._meta.db_tablespace 433 if tablespace and connection.features.supports_tablespaces: 434 tablespace_sql = ' ' + connection.ops.tablespace_sql(tablespace) 435 else: 436 tablespace_sql = '' 437 output.append( 438 style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \ 439 style.SQL_TABLE(qn('%s_%s' % (model._meta.db_table, f.column))) + ' ' + \ 440 style.SQL_KEYWORD('ON') + ' ' + \ 441 style.SQL_TABLE(qn(model._meta.db_table)) + ' ' + \ 442 "(%s)" % style.SQL_FIELD(qn(f.column)) + \ 443 "%s;" % tablespace_sql 444 ) 444 if model._meta.sql_generation_required: 445 for f in model._meta.fields: 446 if f.db_index and not ((f.primary_key or f.unique) and connection.features.autoindexes_primary_keys): 447 unique = f.unique and 'UNIQUE ' or '' 448 tablespace = f.db_tablespace or model._meta.db_tablespace 449 if tablespace and connection.features.supports_tablespaces: 450 tablespace_sql = ' ' + connection.ops.tablespace_sql(tablespace) 451 else: 452 tablespace_sql = '' 453 output.append( 454 style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \ 455 style.SQL_TABLE(qn('%s_%s' % (model._meta.db_table, f.column))) + ' ' + \ 456 style.SQL_KEYWORD('ON') + ' ' + \ 457 style.SQL_TABLE(qn(model._meta.db_table)) + ' ' + \ 458 "(%s)" % style.SQL_FIELD(qn(f.column)) + \ 459 "%s;" % tablespace_sql 460 ) 445 461 return output 446 462 447 463 def emit_post_sync_signal(created_models, verbosity, interactive): -
docs/model-api.txt
1149 1149 that aren't allowed in Python variable names -- notably, the hyphen -- 1150 1150 that's OK. Django quotes column and table names behind the scenes. 1151 1151 1152 ``sql_generation_required`` 1153 --------------------------- 1154 1155 **New in Django development version** 1156 1157 Marks this model as requiring SQL operations when calling ``manage.py``:: 1158 1159 sql_generation_required = True 1160 1161 If this isn't given, Django will use ``sql_generation_required = True`` 1162 what means that the operations like ``manage.py sqlreset``, ``manage.py syncdb`` 1163 and others will regenerate the appropriate table when needed. 1164 If the option is set to False, the appropriate table will not be touched with 1165 any SQL operations. 1166 1167 This is useful for databases where some DB tables are controlled by Django models, 1168 but some DB tables and views are created via raw SQL and should not be affected 1169 by any ``manage.py`` actions. 1170 Note that if the initial SQL data is provided (see `Providing initial SQL 1171 data`_ below), it still will be present in the output of 1172 ``sqlall``/``sqlcustom`` commands. 1173 1152 1174 ``db_tablespace`` 1153 1175 ----------------- 1154 1176