2017-08-30 212 views
0

新的迁移,添加一个简单的表,在迁移过程中给我提供错误“无法添加外键约束”。Django:django.db.utils.IntegrityError:(1215,'无法添加外键约束')

下面是现有模型,称为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 

这里是那么新的模式,我想创建:

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'] 

看起来很简单,对不对?所以我做迁移:

./manage.py makemigrations

到目前为止,一切都很好。然后,我迁移,就像这样:

./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') 

那么,这就是移民本身,在所有是Python的荣耀:

# -*- 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'], 
      }, 
     ), 
    ] 

我试图重新命名的新模式和一切(事件related_name属性),以防我使用某些机器下的变量名,但结果相同。

在线搜索,我只发现Django特别是这个问题的一个例子(Django MySQL error when creating tables),但这并没有帮助。没有迁移到auth,我也不知道为什么会这样做,因为我们既没有与该部分混淆,也没有升级任何软件包。

任何帮助深表谢意。

+0

您是否尝试从“EventLog”中删除引用 –

+0

是的,我有。没有什么区别。谢谢,不过。 :) – Teekin

回答

0

好的,想通了。

我试着手动创建外键,然后用相同的隐含错误消息失败。寻找完全专注于MySQL的解决方案,我在@Andrew的这里找到了一个答案:MySQL Cannot Add Foreign Key Constraint,它详细说明了外键的要求。

其中一个要求是两个表使用相同的引擎类型,可以是InnoDB或MyISAM。事实证明,在我的数据库中,较旧的表是MyISAM,而较新的表是InnoDB,事实上,这是我的问题的根源。

我写了一个简短而非常杂乱的shell脚本来解决这个问题,你可以在下面看到。请注意,它既没有表现也没有美感。只是想弄明白这一点。

#!/bin/bash 

DBNAME=excellent_database 
PASSWORD=very-very-bad-password-on-many-sides-on-many-sides 

# Some of the datetime data in the old MyISAM tables were giving 
# InnoDB a rough time so here they are updated to something InnoDB 
# feels more comfortable with. Subqueries didn't work and I 
# couldn't be bothered to figure out why. 
IDS=$(mysql "$DBNAME" -u root -p"$PASSWORD" -e "SELECT id FROM appname_modelname WHERE timestamp_created = '0000-00-00 00:00:00';") 
for ROW_ID in $IDS; do 
    mysql "$DBNAME" -u root -p"$PASSWORD" -e "UPDATE appname_modelname SET timestamp_created = '0001-01-01 00:00:00' WHERE id = $ROW_ID"; 
    echo $ROW_ID 
done 

mysql "$DBNAME" -u root -p"$PASSWORD" -e "SHOW TABLE STATUS WHERE ENGINE = 'MyISAM';" | awk 'NR>1 {print "ALTER TABLE "$1" ENGINE = InnoDB;"}' | mysql -u root -p"$PASSWORD" "$DBNAME" 

希望它可以帮助别人!

0

变化

eventlog = models.ForeignKey('EventLog', related_name='details') 

eventlog = models.ForeignKey(EventLog, related_name='details') 

;)

+0

它没有区别。谢谢,不过。 :) – Teekin

+0

请发表'django_migrations'表。 – campovski

+1

好问题,@campovski,但我找到了解决方案并将其发布到上面。 :) 感谢您的关注。 – Teekin

0

尝试删除报价:

eventlog = models.ForeignKey(EventLog, related_name='details') 

,或者如果你想使用引号,然后使用APP_NAME也

eventlog = models.ForeignKey('accounts.EventLog', related_name='details') 
+0

试过了。同样的结果。感谢您的回应。 :) – Teekin

相关问题