Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: django.db.utils.IntegrityError: (1215, 'Cannot add foreign key constraint')

A new migration, adding a single, simple table, gives me the error "Cannot add foreign key constraint" during migration.

Here's an existing model, called EventLog:

class EventLog(models.Model):
    """
    The event log.
    """
    user = models.ForeignKey(User, blank=True, null=True)
    timestamp = models.DateTimeField(auto_now=True)
    text = models.TextField(blank=True, null=True)
    ip = models.CharField(max_length=15)
    metadata = JSONField(default={},blank=True)
    product = models.TextField(default=None,blank=True, null=True)
    type = models.ForeignKey(EventType)

    def __unicode__(self):
        return "[%-15s]-[%s] %s (%s)" % (self.type, self.timestamp, self.text, self.user)

    def highlite(self):
        if self.type.highlite:
            return self.type.highlitecss
        return False

Here is then the new model, which I'm trying to create:

class EventLogDetail(models.Model):
    # NOTE: I've already tried switching 'EventLog' out for just EventLog.
    eventlog = models.ForeignKey('EventLog', related_name='details')
    order = models.IntegerField(default=0)
    line = models.CharField(max_length=500)

    class Meta:
        ordering = ['eventlog', 'order']

Seems simple enough, right? So I make the migration:

./manage.py makemigrations:

Migrations for 'accounts':
  accounts/migrations/0016_eventlogdetail.py
    - Create model EventLogDetail

So far, so good. Then, I migrate, like so:

./manage.py migrate:

Operations to perform:
  Apply all migrations: accounts, admin, attention, auth, contenttypes, freedns, hosting, info, mail, sessions, sites, taggit, vserver
Running migrations:
  Applying accounts.0016_eventlogdetail...Traceback (most recent call last):
  File "./manage.py", line 10, in 
    execute_from_command_line(sys.argv)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 363, in execute_from_command_line
    utility.execute()
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 355, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/core/management/base.py", line 283, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/core/management/base.py", line 330, in execute
    output = self.handle(*args, **options)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 204, in handle
    fake_initial=fake_initial,
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 115, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 145, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 244, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/db/backends/base/schema.py", line 93, in __exit__
    self.execute(sql)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/db/backends/base/schema.py", line 120, in execute
    cursor.execute(sql, params)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 101, in execute
    return self.cursor.execute(query, args)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/MySQLdb/cursors.py", line 205, in execute
    self.errorhandler(self, exc, value)
  File "/home/the_user/code/the_project/local/lib/python2.7/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
    raise errorclass, errorvalue
django.db.utils.IntegrityError: (1215, 'Cannot add foreign key constraint')

Here then is migration itself, in all is Pythonic glory:

# -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2017-08-30 12:51
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

    dependencies = [
        ('accounts', '0015_product_public'),
    ]

    operations = [
        migrations.CreateModel(
            name='EventLogDetail',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('order', models.IntegerField(default=0)),
                ('line', models.CharField(max_length=500)),
                ('eventlog', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='details', to='accounts.EventLog')),
            ],
            options={
                'ordering': ['eventlog', 'order'],
            },
        ),
    ]

I've tried renaming the new model and everything in it (event the related_name attribute), in case I were using variable names already taken by some machinery under hood, but with the same results.

Searching online, I've only found one example of this problem with Django specifically (Django MySQL error when creating tables), but that didn't help. There are no migrations to be made to auth, nor can I see why there would be, since we have neither messed with that part nor upgraded any of the packages lately.

Any help deeply appreciated.

like image 361
Teekin Avatar asked Jan 30 '23 16:01

Teekin


1 Answers

My issue was that the database in my Django project is created from scratch and tables are imported from mysql dump. The tables in the mysql dump were of CHARSET utf8mb4 while the new tables which I am creating using migration are created with CHARSET latin1. So the new foreignkey is created in a table with latin1 and referring a table with utf8mb4 which throws the error

Django: django.db.utils.IntegrityError: (1215, 'Cannot add foreign key constraint')

New tables are created with CHARSET latin1 because the default CHARSET of the database which i created was latin1. To check the default CHARSET enter the below command in mysql console.

mysql> SELECT default_character_set_name FROM information_schema.SCHEMATA S WHERE schema_name = "DBNAME";

Workaround for this issue is converting the default CHARSET of database to utf8mb4. This is required not only for fixing the integrity error but also Django will have many other problem if the CHARSET is not utf8. To change the CHARSET of the database use this command.

mysql> ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;
like image 169
Sandeep Balagopal Avatar answered Feb 08 '23 15:02

Sandeep Balagopal