Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#22470 closed Bug (fixed)

Migrations fail with order_with_respect_to and ForeignKey to self

Reported by: Jonas Owned by: Andrew Godwin
Component: Migrations Version: 1.7-beta-1
Severity: Release blocker Keywords: migrations order_with_respect_to
Cc: Jonas, Shai Berger, jezevec, beathan Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Initial migrations for an app with this kind of model setup will fail when running ./manage.py migrate:

class Parent(models.Model):
    spouse = models.ForeignKey('self')

class Child(models.Model):
    parent = models.ForeignKey(Parent)

    class Meta:
        order_with_respect_to = 'parent'

This is the resulting traceback:

  File "./manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/home/jonas/temp/django/django/core/management/__init__.py", line 427, in execute_from_command_line
    utility.execute()
  File "/home/jonas/temp/django/django/core/management/__init__.py", line 419, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/jonas/temp/django/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/home/jonas/temp/django/django/core/management/base.py", line 337, in execute
    output = self.handle(*args, **options)
  File "/home/jonas/temp/django/django/core/management/commands/migrate.py", line 145, in handle
    executor.migrate(targets, plan, fake=options.get("fake", False))
  File "/home/jonas/temp/django/django/db/migrations/executor.py", line 60, in migrate
    self.apply_migration(migration, fake=fake)
  File "/home/jonas/temp/django/django/db/migrations/executor.py", line 88, in apply_migration
    if self.detect_soft_applied(migration):
  File "/home/jonas/temp/django/django/db/migrations/executor.py", line 132, in detect_soft_applied
    apps = project_state.render()
  File "/home/jonas/temp/django/django/db/migrations/state.py", line 48, in render
    model.render(self.apps)
  File "/home/jonas/temp/django/django/db/migrations/state.py", line 232, in render
    body,
  File "/home/jonas/temp/django/django/db/models/base.py", line 298, in __new__
    new_class._prepare()
  File "/home/jonas/temp/django/django/db/models/base.py", line 322, in _prepare
    opts._prepare(cls)
  File "/home/jonas/temp/django/django/db/models/options.py", line 180, in _prepare
    self.order_with_respect_to = self.get_field(self.order_with_respect_to)
  File "/home/jonas/temp/django/django/db/models/options.py", line 397, in get_field
    raise FieldDoesNotExist('%s has no field named %r' % (self.object_name, name))
django.db.models.fields.FieldDoesNotExist: Child has no field named 'parent'

makemigrations creates three migrations:

  • The first migration creates the Child model without the parent field as well as the Parent model without the spouse field.
  • The second migration adds the spouse field to Parent.
  • The third migration adds parent to Child.

The error occurs in the first migration, when the _prepare() wants to access the parent field for order_with_respect_to and can't, as it doesn't exist yet.

I tried adding a test in Django proper but wasn't able to. Will keep trying but support is appreciated.

Change History (11)

comment:1 Changed 2 years ago by Jonas

Cc: Jonas added
Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset

comment:2 Changed 2 years ago by Tim Graham

Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

comment:3 Changed 2 years ago by Andrew Godwin

Owner: changed from nobody to Andrew Godwin
Status: newassigned

Urgh, this is nasty. I'm going to have to find some way of pushing back all Meta changes along with delayed ForeignKeys (this bug will also occur for index_together and unique_together among others).

comment:4 Changed 2 years ago by Shai Berger

Cc: Shai Berger added

This is odd. I'd expect all the fields to be created immediately, and only the constraint creation to be delayed.

comment:5 Changed 2 years ago by Andrew Godwin

Hmm, that might be possible - we could replace the AddField(ForeignKey) with AddField(IntegerField) (or whatever the underlying type is) and then have the second thing be the AlterField to a ForeignKey. I'll try that approach.

comment:6 Changed 2 years ago by jezevec

Cc: jezevec added

comment:7 Changed 2 years ago by beathan

Cc: beathan added

comment:8 Changed 2 years ago by Andrew Godwin

Just noting that this will be fixed as part of the big autodetector rewrite.

comment:9 Changed 2 years ago by Andrew Godwin

This didn't land in the main autodetector merge, but it can now be fixed as that's in place. I plan to add a new operation for alterations to order_with_respect_to (or perhaps just alteration of model options in general) and implement that with proper dependency to fix this.

comment:10 Changed 2 years ago by Andrew Godwin <andrew@…>

Resolution: fixed
Status: assignedclosed

In e5cde2062c0fbe21476978cc318c84134bf7bc46:

[1.7.x] Fixed #22470: Full migration support for order_with_respect_to

comment:11 Changed 2 years ago by Andrew Godwin <andrew@…>

In a8ce5fdc28bdbe091476d49d014d68f8ba4353e7:

Fixed #22470: Full migration support for order_with_respect_to

Note: See TracTickets for help on using tickets.
Back to Top