Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#22411 closed Bug (fixed)

Migrations attempt to create content types without first running contenttypes sync/migrations

Reported by: Stephen Burrows Owned by: nobody
Component: Migrations Version: 1.7-beta-1
Severity: Normal Keywords:
Cc: Stephen Burrows, Tim Graham Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

If I am (for some reason) just migrating a single app on a fresh database, Django will try to create contenttypes for the app's models. But since it hasn't actually synced the contenttypes app yet, the creation fails. While this doesn't seem to affect the actual state of the migrations, it is startling and confusing, and seems unnecessary. I'm not sure which would be better:

  1. Always migrating contenttypes before trying to create.
  2. Only trying to create if contenttypes has already been migrated.
$ ./manage.py migrate <myapp>
Operations to perform:
  Apply all migrations: <myapp>
Running migrations:
  <migrations - all successful>
Traceback (most recent call last):
  File "./manage.py", line 10, in <module>
    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 149, in handle
    emit_post_migrate_signal(created_models, self.verbosity, self.interactive, connection.alias)
  File ".../django/django/core/management/sql.py", line 246, in emit_post_migrate_signal
    using=db)
  File ".../django/django/dispatch/dispatcher.py", line 198, in send
    response = receiver(signal=self, sender=sender, **named)
  File ".../django/django/contrib/auth/management/__init__.py", line 85, in create_permissions
    ctype = ContentType.objects.db_manager(using).get_for_model(klass)
  File ".../django/django/contrib/contenttypes/models.py", line 49, in get_for_model
    defaults={'name': smart_text(opts.verbose_name_raw)},
  File ".../django/django/db/models/manager.py", line 92, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File ".../django/django/db/models/query.py", line 417, in get_or_create
    return self.get(**lookup), False
  File ".../django/django/db/models/query.py", line 346, in get
    num = len(clone)
  File ".../django/django/db/models/query.py", line 122, in __len__
    self._fetch_all()
  File ".../django/django/db/models/query.py", line 961, in _fetch_all
    self._result_cache = list(self.iterator())
  File ".../django/django/db/models/query.py", line 265, in iterator
    for row in compiler.results_iter():
  File ".../django/django/db/models/sql/compiler.py", line 694, in results_iter
    for rows in self.execute_sql(MULTI):
  File ".../django/django/db/models/sql/compiler.py", line 780, in execute_sql
    cursor.execute(sql, params)
  File ".../django/django/db/backends/utils.py", line 77, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File ".../django/django/db/backends/utils.py", line 61, in execute
    return self.cursor.execute(sql, params)
  File ".../django/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File ".../django/django/db/backends/utils.py", line 61, in execute
    return self.cursor.execute(sql, params)
  File ".../django/django/db/backends/sqlite3/base.py", line 479, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such table: django_content_type

Change History (8)

comment:1 by Stephen Burrows, 10 years ago

I would lean towards number 2 (Only trying to create if contenttypes has already been migrated) because explicit is better than implicit.

comment:2 by Tim Graham, 10 years ago

Triage Stage: UnreviewedAccepted

comment:3 by Stephen Burrows, 10 years ago

One option would be to always have a dependency on contenttypes in initial migrations:

dependencies = [
    ('contenttypes', '__first__'),
]

Untested, but I think it would work.

comment:4 by Tim Graham, 10 years ago

Cc: Tim Graham added

I don't think adding a dependency on contenttypes would be wise since the app should be optional and if we added that then if django.contrib.contenttypes isn't in INSTALLED_APPS, you'd get an error when migrating: ValueError: Dependency on unknown app contenttypes. This raises a more general issue that unlike the post_syncdb signal, when post_migrate is fired there's no guarantee that the tables for all other apps will exist. I'm not sure if there's an existing method to check whether or not a model's table has been created.

comment:5 by Stephen Burrows, 10 years ago

This *should* be resolved by #22485, but I can't test myself due to the introduction of #22563.

comment:6 by Tim Graham, 10 years ago

It still appears an issue, but I wonder if we should just document this or throw a more helpful error message?

comment:7 by Andrew Godwin <andrew@…>, 10 years ago

Resolution: fixed
Status: newclosed

In 7a259008a76c5bcd6c1e5ba3a45d17a6184c4242:

Fixed #22411: Throw a more helpful error if contenttypes doesn't exist.

comment:8 by Andrew Godwin <andrew@…>, 10 years ago

In c5578ba9fa052a814c27fe0069f98ed994751634:

[1.7.x] Fixed #22411: Throw a more helpful error if contenttypes doesn't exist.

Conflicts:

django/contrib/contenttypes/models.py

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