id summary reporter owner description type status component version severity resolution keywords cc stage has_patch needs_docs needs_tests needs_better_patch easy ui_ux 22397 Issues removing M2M field with explicit through model Stephen Burrows andrewsg "I get the error below when I try to delete a field that has an explicit through model. It comes down to: for some reason, field.rel.through is a string instead of being resolved to a model (maybe in part because the model has been deleted already?) {{{ File ""./manage.py"", line 10, in execute_from_command_line(sys.argv) File "".../django/django/core/management/__init__.py"", line 427, in execute_from_command_line utility.execute() File "".../django/django/core/management/__init__.py"", line 419, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "".../django/django/core/management/base.py"", line 288, in run_from_argv self.execute(*args, **options.__dict__) File "".../django/django/core/management/base.py"", line 337, in execute output = self.handle(*args, **options) File "".../django/django/core/management/commands/migrate.py"", line 145, in handle executor.migrate(targets, plan, fake=options.get(""fake"", False)) File "".../django/django/db/migrations/executor.py"", line 60, in migrate self.apply_migration(migration, fake=fake) File "".../django/django/db/migrations/executor.py"", line 94, in apply_migration migration.apply(project_state, schema_editor) File "".../django/django/db/migrations/migration.py"", line 97, in apply operation.database_forwards(self.app_label, schema_editor, project_state, new_state) File "".../django/django/db/migrations/operations/fields.py"", line 83, in database_forwards schema_editor.remove_field(from_model, from_model._meta.get_field_by_name(self.name)[0]) File "".../django/django/db/backends/sqlite3/schema.py"", line 125, in remove_field if isinstance(field, ManyToManyField) and field.rel.through._meta.auto_created: AttributeError: 'str' object has no attribute '_meta' }}} If I reverse the order of operations (so that the field is removed *before* the through model is deleted) I get the following error: {{{ File ""./manage.py"", line 10, in execute_from_command_line(sys.argv) File "".../django/django/core/management/__init__.py"", line 427, in execute_from_command_line utility.execute() File "".../django/django/core/management/__init__.py"", line 419, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "".../django/django/core/management/base.py"", line 288, in run_from_argv self.execute(*args, **options.__dict__) File "".../django/django/core/management/base.py"", line 337, in execute output = self.handle(*args, **options) File "".../django/django/core/management/commands/migrate.py"", line 145, in handle executor.migrate(targets, plan, fake=options.get(""fake"", False)) File "".../django/django/db/migrations/executor.py"", line 60, in migrate self.apply_migration(migration, fake=fake) File "".../django/django/db/migrations/executor.py"", line 94, in apply_migration migration.apply(project_state, schema_editor) File "".../django/django/db/migrations/migration.py"", line 97, in apply operation.database_forwards(self.app_label, schema_editor, project_state, new_state) File "".../django/django/db/migrations/operations/fields.py"", line 83, in database_forwards schema_editor.remove_field(from_model, from_model._meta.get_field_by_name(self.name)[0]) File "".../django/django/db/backends/sqlite3/schema.py"", line 128, in remove_field self._remake_table(model, delete_fields=[field]) File "".../django/django/db/backends/sqlite3/schema.py"", line 65, in _remake_table del body[field.name] KeyError: 'items' }}} Model is changing from {{{ class ItemDiscount(models.Model): PERCENT = 'percent' FLAT = 'flat' TYPE_CHOICES = ( (PERCENT, _('Percent')), (FLAT, _('Flat')), ) item = models.ForeignKey(Item) discount = models.ForeignKey('Discount') discount_type = models.CharField(max_length=7, choices=TYPE_CHOICES, default=PERCENT) amount = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True, validators=[MinValueValidator(0)]) class Discount(models.Model): name = models.CharField(max_length=40) code = models.CharField(max_length=20) items = models.ManyToManyField(Item, through=ItemDiscount) available_start = models.DateTimeField() available_end = models.DateTimeField() event = models.ForeignKey(Event) class Meta: unique_together = ('code', 'event') }}} to {{{ class Discount(models.Model): PERCENT = 'percent' FLAT = 'flat' TYPE_CHOICES = ( (PERCENT, _('Percent')), (FLAT, _('Flat')), ) name = models.CharField(max_length=40) code = models.CharField(max_length=20) item_option = models.ForeignKey(ItemOption) available_start = models.DateTimeField(blank=True, null=True) available_end = models.DateTimeField(blank=True, null=True) discount_type = models.CharField(max_length=7, choices=TYPE_CHOICES, default=PERCENT) amount = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True, validators=[MinValueValidator(0)]) event = models.ForeignKey(Event) class Meta: unique_together = ('code', 'event') }}}" Bug closed Migrations dev Release blocker fixed Stephen Burrows loic@… Accepted 0 0 0 0 0 0