2017-08-30 208 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

相關問題