使用南(django)和 MySQL 进行模式迁移

Posted

技术标签:

【中文标题】使用南(django)和 MySQL 进行模式迁移【英文标题】:Schema migration with south (django) and MySQL 【发布时间】:2011-12-07 06:25:12 【问题描述】:

我只是在浏览一个关于 django 的教程,并且我遵循了每一步,但每次尝试迁移时仍然出现此错误:

初始迁移有效,但尝试迁移它,我明白了:

  root@debian:/Sites/tumblog# ./manage.py migrate blog

   Traceback (most recent call last):
  File "manage.py", line 11, in <module>
    execute_manager(settings)
  File "/usr/lib/pymodules/python2.6/django/core/management/__init__.py", line 438, in execute_manager
    utility.execute()
  File "/usr/lib/pymodules/python2.6/django/core/management/__init__.py", line 379, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/lib/pymodules/python2.6/django/core/management/base.py", line 191, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/usr/lib/pymodules/python2.6/django/core/management/base.py", line 220, in execute
    output = self.handle(*args, **options)
  File "/usr/lib/pymodules/python2.6/south/management/commands/migrate.py", line 102, in handle
    delete_ghosts = delete_ghosts,
  File "/usr/lib/pymodules/python2.6/south/migration/__init__.py", line 202, in migrate_app
    success = migrator.migrate_many(target, workplan, database)
  File "/usr/lib/pymodules/python2.6/south/migration/migrators.py", line 215, in migrate_many
    result = migrator.__class__.migrate_many(migrator, target, migrations, database)
  File "/usr/lib/pymodules/python2.6/south/migration/migrators.py", line 284, in migrate_many
    result = self.migrate(migration, database)
  File "/usr/lib/pymodules/python2.6/south/migration/migrators.py", line 121, in migrate
    result = self.run(migration)
  File "/usr/lib/pymodules/python2.6/south/migration/migrators.py", line 95, in run
    return self.run_migration(migration)
  File "/usr/lib/pymodules/python2.6/south/migration/migrators.py", line 77, in run_migration
    migration_function()
  File "/usr/lib/pymodules/python2.6/south/migration/migrators.py", line 56, in <lambda>
    return (lambda: direction(orm))
  File "/Site/tumblog/blog/migrations/0005_initial.py", line 17, in forwards
    ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
  File "/usr/lib/pymodules/python2.6/south/db/generic.py", line 210, in create_table
    ', '.join([col for col in columns if col]),
  File "/usr/lib/pymodules/python2.6/south/db/generic.py", line 134, in execute
    cursor.execute(sql, params)
  File "/usr/lib/pymodules/python2.6/django/db/backends/util.py", line 15, in execute
    return self.cursor.execute(sql, params)
  File "/usr/lib/pymodules/python2.6/django/db/backends/mysql/base.py", line 86, in execute
    return self.cursor.execute(query, args)
  File "/usr/lib/pymodules/python2.6/MySQLdb/cursors.py", line 166, in execute
    self.errorhandler(self, exc, value)
  File "/usr/lib/pymodules/python2.6/MySQLdb/connections.py", line 35, in defaulterrorhandler
    raise errorclass, errorvalue
_mysql_exceptions.OperationalError: (1050, "Table 'blog_blog' already exists")

我四处搜索,发现添加 --fake 会跳过这个错误,但它不会改变什么?这里有什么问题,我该如何解决?

【问题讨论】:

【参考方案1】:

您的迁移中实际发生了什么?如果您收到此错误,那么在初始迁移之前,您的数据库中已经存在 blog_blogblog_blog 会调用两次 create_table(可能是之前尝试创建从未迁移过的博客的遗留问题)为零)。

如果错误是在初始迁移完成之前发生的,那么它很可能是人为因素,您可以手动将其从数据库中删除,然后重试。如果初始迁移成功,但后来的迁移失败,则查找 create_tableblog_blog 重复的位置。

【讨论】:

【参考方案2】:

问题是迁移尝试创建的表已经存在于数据库中。它们必须是使用 syncdb 创建的(如果您使用 syncdb 并稍后开始使用 south 作为应用程序,您会得到这个),或者是通过以前的迁移创建的。

迁移的名称是0005_initial 很可疑。 0001-0004 迁移在做什么?

要解决您的问题,您首先应确保没有重复迁移(例如,0001_initial 创建表,然后 0005_initial 尝试再次执行此操作)。您只需要对应用进行一次初始迁移,接下来的迁移应该只记录对架构的更改。

然后,从数据库中删除表并重新创建它们。类似的东西可能会起作用:

./manage.py migrate [appname] --fake
./manage.py migrate [appname] zero
./manage.py migrate [appname]

如果失败(如果迁移中同时存在现有表和新表,则会失败) - 那么您必须在 mysql 控制台中手动删除表。

【讨论】:

【参考方案3】:

您确定添加 --fake 不会改变任何东西吗?

manage.py migrate blog --fake

...或从 mysql 控制台手动删除表 'blog_blog' ;)

【讨论】:

以上是关于使用南(django)和 MySQL 进行模式迁移的主要内容,如果未能解决你的问题,请参考以下文章

南迁移和 django 迁移有啥区别?

Django 南迁移 - 添加 FULLTEXT 索引

测试使用南迁移的 Django 应用程序

Django 1.7 内置迁移与南迁移?

南迁移错误:django.contrib.auth 的 NoMigrations 异常

如何在南迁移期间调用 django 模型类的静态方法