Ticket #2720: any-order2720.diff
File any-order2720.diff, 7.2 KB (added by , 18 years ago) |
---|
-
django/core/management.py
112 112 final_output.extend(_get_sql_for_pending_references(model, pending_references)) 113 113 # Keep track of the fact that we've created the table for this model. 114 114 known_models.add(model) 115 # Create the many-to-many join tables. 116 final_output.extend(_get_many_to_many_sql_for_model(model,known_models,pending_references)) 115 117 116 # Create the many-to-many join tables.117 for model in app_models:118 final_output.extend(_get_many_to_many_sql_for_model(model))119 120 118 # Handle references to tables that are from other apps 121 119 # but don't exist physically 122 120 not_installed_models = set(pending_references.keys()) … … 145 143 opts = model._meta 146 144 final_output = [] 147 145 table_output = [] 146 constraints = [] 148 147 pending_references = {} 149 148 for f in opts.fields: 150 149 if isinstance(f, (models.ForeignKey, models.OneToOneField)): … … 165 164 field_output.append(style.SQL_KEYWORD('PRIMARY KEY')) 166 165 if f.rel: 167 166 if f.rel.to in known_models: 168 field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \167 ref_text=style.SQL_KEYWORD('REFERENCES') + ' ' + \ 169 168 style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)) + ' (' + \ 170 169 style.SQL_FIELD(backend.quote_name(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')' 171 ) 170 field_output.append(ref_text) 171 constraints.append('FOREIGN KEY (%s) %s' % \ 172 (style.SQL_FIELD(backend.quote_name(f.column)), 173 ref_text)) 172 174 else: 173 175 # We haven't yet created the table to which this field 174 176 # is related, so save it for later. … … 178 180 table_output.append(style.SQL_FIELD(backend.quote_name('_order')) + ' ' + \ 179 181 style.SQL_COLTYPE(data_types['IntegerField']) + ' ' + \ 180 182 style.SQL_KEYWORD('NULL')) 183 table_output += constraints 181 184 for field_constraints in opts.unique_together: 182 185 table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \ 183 186 ", ".join([backend.quote_name(style.SQL_FIELD(opts.get_field(f).column)) for f in field_constraints])) … … 198 201 data_types = get_creation_module().DATA_TYPES 199 202 200 203 final_output = [] 201 if backend.supports_constraints :204 if backend.supports_constraints and model in pending_references: 202 205 opts = model._meta 203 if model in pending_references: 204 for rel_class, f in pending_references[model]: 205 rel_opts = rel_class._meta 206 r_table = rel_opts.db_table 206 table = opts.db_table 207 for rel_class, f in pending_references[model]: 208 if type(rel_class) == dict: 209 r_table = rel_class['table'] 210 r_col = rel_class['col'] 211 col = opts.pk.column 212 else: 213 r_table = rel_class._meta.db_table 207 214 r_col = f.column 208 table = opts.db_table209 215 col = opts.get_field(f.rel.field_name).column 210 211 212 213 214 215 216 216 # For MySQL, r_name must be unique in the first 64 characters. 217 # So we are careful with character usage here. 218 r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table)))) 219 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \ 220 (backend.quote_name(r_table), r_name, 221 backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col))) 222 del pending_references[model] 217 223 return final_output 218 224 219 def _get_many_to_many_sql_for_model(model ):225 def _get_many_to_many_sql_for_model(model,known_models,pending_references): 220 226 from django.db import backend, get_creation_module 221 227 from django.db.models import GenericRel 222 228 … … 224 230 225 231 opts = model._meta 226 232 final_output = [] 233 227 234 for f in opts.many_to_many: 228 235 if not isinstance(f.rel, GenericRel): 229 236 table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \ … … 244 251 style.SQL_KEYWORD('NOT NULL REFERENCES'), 245 252 style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)), 246 253 style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column)))) 254 table_output.append(' FOREIGN KEY (%s) REFERENCES %s (%s),' % \ 255 (style.SQL_FIELD(backend.quote_name(f.m2m_column_name())), 256 style.SQL_TABLE(backend.quote_name(opts.db_table)), 257 style.SQL_FIELD(backend.quote_name(opts.pk.column)))) 258 if f.rel.to in known_models: 259 table_output.append(' FOREIGN KEY (%s) REFERENCES %s (%s),' % \ 260 (style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name())), 261 style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)), 262 style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column)))) 263 else: 264 pending_references.setdefault(f.rel.to, []).append( 265 ({'table':f.m2m_db_table(),'col':f.m2m_reverse_name()}, f)) 247 266 table_output.append(' %s (%s, %s)' % \ 248 267 (style.SQL_KEYWORD('UNIQUE'), 249 268 style.SQL_FIELD(backend.quote_name(f.m2m_column_name())), … … 485 504 for statement in sql: 486 505 cursor.execute(statement) 487 506 table_list.append(model._meta.db_table) 507 sql = _get_many_to_many_sql_for_model(model,seen_models,pending_references) 508 if sql: 509 if verbosity >= 2: 510 print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name) 511 for statement in sql: 512 cursor.execute(statement) 488 513 489 for model in model_list:490 if model in created_models:491 sql = _get_many_to_many_sql_for_model(model)492 if sql:493 if verbosity >= 2:494 print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name)495 for statement in sql:496 cursor.execute(statement)497 498 514 transaction.commit_unless_managed() 499 515 500 516 # Send the post_syncdb signal, so individual apps can do whatever they need