简体   繁体   中英

Django 1.8 app mysteriously fails with initial migration due to errno: 150 "Foreign key constraint is incorrectly formed"

I'm writing an app in django 1.8 with python 3.4 and I'm encountering an issue with using MySQL as the database backend which has got me completely stumped.

When I start off with a new database and call./manage.py migrate (or syncdb) and it tries to create the initial database, I get the following traceback:

(virtualenv)~/projects/projmoj (master ✘)✹✭ ᐅ ./manage.py migrate
Operations to perform:
  Synchronize unmigrated apps: allauth, rest_framework, registration, rest_auth, projmoj, messages, project, staticfiles
  Apply all migrations: contenttypes, sites, sessions, task, auth, admin, authtoken, static_precompiler, account
Synchronizing apps without migrations:
  Creating tables...
    Creating table project_project
    Creating table project_membership
    Running deferred SQL...
Traceback (most recent call last):
  File "/home/tobbe/projects/projmoj/virtualenv/lib/python3.4/site-packages/django/db/backends/utils.py", line 62, in execute
    return self.cursor.execute(sql)
  File "/home/tobbe/projects/projmoj/virtualenv/lib/python3.4/site-packages/django/db/backends/mysql/base.py", line 124, in execute
    return self.cursor.execute(query, args)
  File "/home/tobbe/projects/projmoj/virtualenv/lib/python3.4/site-packages/MySQLdb/cursors.py", line 220, in execute
    self.errorhandler(self, exc, value)
  File "/home/tobbe/projects/projmoj/virtualenv/lib/python3.4/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
    raise errorvalue
  File "/home/tobbe/projects/projmoj/virtualenv/lib/python3.4/site-packages/MySQLdb/cursors.py", line 209, in execute
    r = self._query(query)
  File "/home/tobbe/projects/projmoj/virtualenv/lib/python3.4/site-packages/MySQLdb/cursors.py", line 371, in _query
    rowcount = self._do_query(q)
  File "/home/tobbe/projects/projmoj/virtualenv/lib/python3.4/site-packages/MySQLdb/cursors.py", line 335, in _do_query
    db.query(q)
  File "/home/tobbe/projects/projmoj/virtualenv/lib/python3.4/site-packages/MySQLdb/connections.py", line 280, in query
    _mysql.connection.query(self, query)
_mysql_exceptions.OperationalError: (1005, 'Can\'t create table `tasks`.`#sql-1c32_9` (errno: 150 "Foreign key constraint is incorrectly formed")')

This error happens when I do the same on a web hosting service, it works however using sqlite on both the hosting service and localhost.

I have no migrations, and these are my models:

class Project(models.Model):
  name = models.CharField(max_length = 32) 
  description = models.TextField(null=True, blank=True)
  creation_date = models.DateTimeField(auto_now_add=True)

  def get_owner(self):
    return self.members.filter(status=OWNER).first().user

  def get_membership(self, user):
    return self.members.filter(user=user).first()

  def __str__(self):
    return str(self.name) + " - by " + str(self.get_owner().username)

class Membership(models.Model):
  user = models.ForeignKey(User, related_name='joined_projects')
  project = models.ForeignKey(Project, related_name='members')
  status = models.PositiveSmallIntegerField(choices=MEMBER_STATUS)
  join_date = models.DateTimeField(auto_now_add=True)

  def __str__(self):
    return str(self.user.username)

class Sprint(models.Model):
  name = models.CharField(max_length = 32, null=True, blank=True)
  start_date = models.DateTimeField()
  due_date = models.DateTimeField(null=True, blank=True)
  project = models.ForeignKey(Project, related_name='sprints')
  status = models.PositiveSmallIntegerField(choices=SPRINT_STATUS, default=PLANNING)

  def __str__(self):
    return str(self.name) + " - " + str(self.project)

class Category(models.Model):
  name = models.CharField(max_length = 32) 
  project = models.ForeignKey(Project, related_name='categories')

  def __str__(self):
    return str(self.name) + " - " + str(self.project)

class Goal(models.Model):
  name = models.CharField(max_length = 32) 
  description = models.TextField(null=True, blank=True)
  project = models.ForeignKey(Project, related_name='goals')
  completion = models.PositiveSmallIntegerField(choices=COMPLETION, default=NOT_COMPLETED)

  def __str__(self):
    return str(self.name) + " - " + str(self.project)

class Task(models.Model):
  name = models.CharField(max_length = 64)
  description = models.TextField(null=True, blank=True)
  project = models.ForeignKey(Project, related_name='tasks')
  category = models.ForeignKey(Category, related_name='tasks', null=True, blank=True)
  goal = models.ForeignKey(Goal, related_name='tasks', null=True, blank=True)
  creation_date = models.DateTimeField(auto_now_add=True)
  sprint = models.ForeignKey(Sprint, related_name='tasks', null=True, blank=True)
  status = models.PositiveSmallIntegerField(choices=TASK_STATUS, default=WAITING)
  dedicated_hours = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
  assigned_worker = models.ForeignKey(User, null=True, blank=True)
  priority = models.PositiveSmallIntegerField(choices=PRIORITY, default=NORMAL)

  def __str__(self):
    return str(self.name) + " - " + str(self.project)

class HourReport(models.Model):
  task = models.ForeignKey(Task, related_name='hour_reports')
  worker = models.ForeignKey(User, related_name='hour_reports')
  hours_spent = models.DecimalField(max_digits=6, decimal_places=2)
  date = models.DateTimeField(auto_now_add=True)

  def __str__(self):
    return str(self.hours_spent) + " on " + str(self.task)

My database settings:

DATABASES = { 
  'default': {
      'ENGINE': 'django.db.backends.mysql',
      'NAME': 'tasks',
      'USER': 'root',
      'PASSWORD': 'mysqlmysql',
      'HOST': 'localhost',
  }
}

Versions etc:

  • Django 1.8
  • Python 3.4
  • Default storage engine: InnoDB
  • Mysqlclient 1.3.6
  • Server: MySQL 5.5.42 on Amazon RDS (at web hosting)
  • Server: 10.0.21-MariaDB-log MariaDB Server (localhost)

When googling it seems like this error is often when people stuff up their manual SQL code, but I am doing it all automatically through django.

Any ideas?

The log is telling you that you have not created migrations for your project app. You should create migrations for the app before running migrate.

./manage.py makemigrations project
./manage.py migrate

Since it's a new database, you'd be better to completely reset it before creating and applying the migrations, otherwise you'll have to manually deal with its current inconsistent state.

According to the Django documentation MySQL notes. Storage engine

If you upgrade an existing project to MySQL 5.5.5 and subsequently add some tables, ensure that your tables are using the same storage engine (ie MyISAM vs. InnoDB ). Specifically, if tables that have a ForeignKey between them use different storage engines, you may see an error like the following when running migrate :

 _mysql_exceptions.OperationalError: ( 1005, "Can't create table '\\\\db_name\\\\.#sql-4a8_ab' (errno: 150)" )

Stop you backend and do backup. Than change storage engine for tables from MyISAM to InnoDB. It's fix the problem.

Also in the MySQL docs ( B.3 Server Error Codes and Messages chapter) specified about this error:

Error: 1005 SQLSTATE: HY000 (ER_CANT_CREATE_TABLE)

Message: Can't create table '%s' (errno: %d - %s)

InnoDB reports this error when a table cannot be created. If the error message refers to error 150, table creation failed because a foreign key constraint was not correctly formed. If the error message refers to error −1, table creation probably failed because the table includes a column name that matched the name of an internal InnoDB table.

It's also possible when running python manage.py migrate to get that error of

_mysql.connection.query(self, query)

django.db.utils.OperationalError: (1005, 'Can\\'t create table > codelabs . django_admin_log (errno: 150 "Foreign key constraint is incorrectly formed")')

due to having wrong information in settings.py regarding the DATABASES. For instances, if in your database your table has the name tiago p eres and in your settings.py you're refering the NAME to be tiago P eres , that error will show up. To fix it, just use the correct NAME and run again python manage.py migrate .

I also ran into this issue today and read articles and StackOverflow which didn't solve the issue. Then I deleted my database as there was nothing special and removed all migration files and started the migration process again. Issue solved.

Look at the output of the command SHOW ENGINE INNODB STATUS in MySql or MariaDB console client ( mariadb link , mysql link ). It`s more informative. For example, it showed me this message:

...
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2021-09-20 18:27:08 7faea3ad1700 Error in foreign key constraint of table `my_db`.`django_admin_log`:
Alter  table `my_db`.`django_admin_log` with foreign key constraint failed. Referenced table `my_db`.`profiles_userprofile` not found in the data dictionary near ' FOREIGN KEY (`user_id`) REFERENCES `profiles_userprofile` (`id`)'.
...

It said to me that I forgot to create migrations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM