def rename_model(self, app_label, old_name, new_name): # Add a new model. old_name_lower = old_name.lower() new_name_lower = new_name.lower() renamed_model = self.models[app_label, old_name_lower].clone() renamed_model.name = new_name self.models[app_label, new_name_lower] = renamed_model # Repoint all fields pointing to the old model to the new one. old_model_tuple = (app_label, old_name_lower) new_remote_model = f'{app_label}.{new_name}' to_reload = set() for model_state, name, field, reference in get_references( self, old_model_tuple): changed_field = None if reference.to: changed_field = field.clone() changed_field.remote_field.model = new_remote_model if reference.through: if changed_field is None: changed_field = field.clone() changed_field.remote_field.through = new_remote_model if changed_field: model_state.fields[name] = changed_field to_reload.add((model_state.app_label, model_state.name_lower)) # Reload models related to old model before removing the old model. self.reload_models(to_reload, delay=True) # Remove the old model. self.remove_model(app_label, old_name_lower) self.reload_model(app_label, new_name_lower, delay=True)
def rename_field(self, app_label, model_name, old_name, new_name): model_key = app_label, model_name model_state = self.models[model_key] # Rename the field. fields = model_state.fields try: found = fields.pop(old_name) except KeyError: raise FieldDoesNotExist( f"{app_label}.{model_name} has no field named '{old_name}'" ) fields[new_name] = found for field in fields.values(): # Fix from_fields to refer to the new field. from_fields = getattr(field, "from_fields", None) if from_fields: field.from_fields = tuple( [ new_name if from_field_name == old_name else from_field_name for from_field_name in from_fields ] ) # Fix index/unique_together to refer to the new field. options = model_state.options for option in ("index_together", "unique_together"): if option in options: options[option] = [ [new_name if n == old_name else n for n in together] for together in options[option] ] # Fix to_fields to refer to the new field. delay = True references = get_references(self, model_key, (old_name, found)) for *_, field, reference in references: delay = False if reference.to: remote_field, to_fields = reference.to if getattr(remote_field, "field_name", None) == old_name: remote_field.field_name = new_name if to_fields: field.to_fields = tuple( [ new_name if to_field_name == old_name else to_field_name for to_field_name in to_fields ] ) if self._relations is not None: old_name_lower = old_name.lower() new_name_lower = new_name.lower() for to_model in self._relations.values(): if old_name_lower in to_model[model_key]: field = to_model[model_key].pop(old_name_lower) field.name = new_name_lower to_model[model_key][new_name_lower] = field self.reload_model(*model_key, delay=delay)
def state_forwards(self, app_label, state): model_state = state.models[app_label, self.model_name_lower] # Rename the field fields = model_state.fields try: found = fields.pop(self.old_name) except KeyError: raise FieldDoesNotExist( "%s.%s has no field named '%s'" % (app_label, self.model_name, self.old_name)) fields[self.new_name] = found for field in fields.values(): # Fix from_fields to refer to the new field. from_fields = getattr(field, 'from_fields', None) if from_fields: field.from_fields = tuple([ self.new_name if from_field_name == self.old_name else from_field_name for from_field_name in from_fields ]) # Fix index/unique_together to refer to the new field options = model_state.options for option in ('index_together', 'unique_together'): if option in options: options[option] = [[ self.new_name if n == self.old_name else n for n in together ] for together in options[option]] # Fix to_fields to refer to the new field. delay = True references = get_references( state, (app_label, self.model_name_lower), (self.old_name, found), ) for *_, field, reference in references: delay = False if reference.to: remote_field, to_fields = reference.to if getattr(remote_field, 'field_name', None) == self.old_name: remote_field.field_name = self.new_name if to_fields: field.to_fields = tuple([ self.new_name if to_field_name == self.old_name else to_field_name for to_field_name in to_fields ]) state.reload_model(app_label, self.model_name_lower, delay=delay)
def rename_field(self, app_label, model_name, old_name, new_name): model_state = self.models[app_label, model_name] # Rename the field. fields = model_state.fields try: found = fields.pop(old_name) except KeyError: raise FieldDoesNotExist( f"{app_label}.{model_name} has no field named '{old_name}'") fields[new_name] = found for field in fields.values(): # Fix from_fields to refer to the new field. from_fields = getattr(field, 'from_fields', None) if from_fields: field.from_fields = tuple([ new_name if from_field_name == old_name else from_field_name for from_field_name in from_fields ]) # Fix index/unique_together to refer to the new field. options = model_state.options for option in ('index_together', 'unique_together'): if option in options: options[option] = [[ new_name if n == old_name else n for n in together ] for together in options[option]] # Fix to_fields to refer to the new field. delay = True references = get_references(self, (app_label, model_name), (old_name, found)) for *_, field, reference in references: delay = False if reference.to: remote_field, to_fields = reference.to if getattr(remote_field, 'field_name', None) == old_name: remote_field.field_name = new_name if to_fields: field.to_fields = tuple([ new_name if to_field_name == old_name else to_field_name for to_field_name in to_fields ]) self.reload_model(app_label, model_name, delay=delay)