Running migrations crashes if embedded models are created before the models in which they are used

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: django
    • None
    • None
    • Python Drivers
    • None
    • None
    • None
    • None
    • None
    • None

      Following the change where embedded model references  are serialized as strings (INTPYTHON-916), migrate will crash if CreateModel operations aren't ordered properly. For example, given these models:

       

      class Billing(EmbeddedModel):
          ...
      
      class PatientRecord(EmbeddedModel):
          billing = EmbeddedModelField(Billing)
      
      class Patient(models.Model):
          patient_record = EmbeddedModelField(PatientRecord)
      

      makemigrations generates CreateModel operations in alphabetical order: Billing, Patient, PatientRecord. That leads to the following crash because the `PatientRecord` model cannot be resolved at the CreateModel(Patient) stage.

      $ python manage.py migrate emb
      Operations to perform:
        Apply all migrations: emb
      Running migrations:
        Applying emb.0001_initial...Traceback (most recent call last):
        File "/home/tim/code/mysite/manage.py", line 10, in <module>
          execute_from_command_line(sys.argv)
        File "/home/tim/code/django/django/core/management/__init__.py", line 443, in execute_from_command_line
          utility.execute()
        File "/home/tim/code/django/django/core/management/__init__.py", line 437, in execute
          self.fetch_command(subcommand).run_from_argv(self.argv)
        File "/home/tim/code/django/django/core/management/base.py", line 420, in run_from_argv
          self.execute(*args, **cmd_options)
        File "/home/tim/code/django/django/core/management/base.py", line 464, in execute
          output = self.handle(*args, **options)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/tim/code/django/django/core/management/base.py", line 111, in wrapper
          res = handle_func(*args, **kwargs)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/tim/code/django/django/core/management/commands/migrate.py", line 354, in handle
          post_migrate_state = executor.migrate(
                               ^^^^^^^^^^^^^^^^^
        File "/home/tim/code/django/django/db/migrations/executor.py", line 137, in migrate
          state = self._migrate_all_forwards(
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/tim/code/django/django/db/migrations/executor.py", line 169, in _migrate_all_forwards
          state = self.apply_migration(
                  ^^^^^^^^^^^^^^^^^^^^^
        File "/home/tim/code/django/django/db/migrations/executor.py", line 257, in apply_migration
          state = migration.apply(state, schema_editor)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/tim/code/django/django/db/migrations/migration.py", line 132, in apply
          operation.database_forwards(
        File "/home/tim/code/django/django/db/migrations/operations/models.py", line 100, in database_forwards
          schema_editor.create_model(model)
        File "/home/tim/code/django-mongodb/django_mongodb_backend/query.py", line 20, in wrapper
          return func(*args, **kwargs)
                 ^^^^^^^^^^^^^^^^^^^^^
        File "/home/tim/code/django-mongodb/django_mongodb_backend/schema.py", line 29, in wrapper
          func(self, model, *args, **kwargs)
        File "/home/tim/code/django-mongodb/django_mongodb_backend/schema.py", line 48, in create_model
          self._create_collection(model)
        File "/home/tim/code/django-mongodb/django_mongodb_backend/schema.py", line 455, in _create_collection
          if model_has_encrypted_fields(model):
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/tim/code/django-mongodb/django_mongodb_backend/utils.py", line 160, in model_has_encrypted_fields
          return any(
                 ^^^^
        File "/home/tim/code/django-mongodb/django_mongodb_backend/utils.py", line 164, in <genexpr>
          and model_has_encrypted_fields(field.embedded_model)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/tim/code/django-mongodb/django_mongodb_backend/utils.py", line 166, in model_has_encrypted_fields
          for field in model._meta.fields
                       ^^^^^^^^^^^
      AttributeError: 'str' object has no attribute '_meta'

      The migrations autodetector must generate CreateModel operations so that dependent models appear first.

            Assignee:
            Tim Graham
            Reporter:
            Tim Graham
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: