Django 1.7迁移不重新创建已删除的表,为什么?

45 投票
10 回答
31579 浏览
提问于 2025-05-01 07:05

我在使用Django 1.7的迁移功能。

我不小心把数据库中的一个表删掉了。我以为重新运行迁移就能把这个表重新创建出来,但结果并不是这样,Django提示说“没有迁移可以应用”。

我该怎么做才能让Django重新创建这个表呢?

我已经运行了:

> makemigrations - No changes detected
> migrate - No migrations to apply.

我尝试对模型做了一些修改,然后运行新的迁移,但系统只是提示“表'x.test_customer'不存在”,这确实是对的,但我希望的是它能重新创建这个表。

暂无标签

10 个回答

6

在我的情况下,使用的是 django 2.0.2,为了重新创建被删除的表,我需要先把 myapp 中的模型注释掉,然后用 --fake 进行迁移,接着再把模型取消注释,并且进行不带 --fake 的迁移。这个过程和raul的回答稍有不同:

  1. 删除你想要的应用中的迁移文件。
  2. 根据raul的回答:在数据库中执行 DELETE FROM django_migrations WHERE app = 'app_name'
  3. models.py 中注释掉代码,以及在 viewssignals 等地方使用这些模型的代码(这样可以避免错误)。
  4. 运行 python manage.py makemigrations YOUR_APP_NAME
  5. 运行 python manage.py migrate --fake
  6. 取消注释在第3步中注释掉的内容。
  7. 再次运行 python manage.py makemigrations YOUR_APP_NAME
  8. 进行不带 --fake 的迁移:运行 python manage.py migrate

这样应该能解决一些用户的问题。

7

我其实找到了一种更简单的方法来解决这个问题。你可以假装撤销那些并不存在的东西,然后再重新迁移。如果你的迁移文件0005是用来创建表的:

python manage.py migrate myapp --fake 0004
python manage.py migrate myapp

这样应该就没问题了!

如果你需要跳过后面的迁移,可以这样做:

python manage.py migrate myapp --fake 0004
python manage.py migrate myapp 0005
python manage.py migrate myapp --fake

这样应该也没问题了!

26

我找到的另一个解决方案,效果非常好:

在 Django 1.7 版本中:

  1. 删除你的迁移文件夹

  2. 在数据库中执行:DELETE FROM django_migrations WHERE app = 'app_name'

    你也可以选择直接清空这个表。

  3. 运行 python manage.py makemigrations

  4. 运行 python manage.py migrate --fake

在 Django 1.9.5 版本中:

  1. 删除你的迁移文件夹

  2. 在数据库中执行:DELETE FROM django_migrations WHERE app = 'app_name'

    你也可以选择直接清空这个表。

  3. 运行 python manage.py makemigrations app_name

  4. 运行 python manage.py migrate

这个方法对我来说效果百分之百好用!

66

去你的数据库里,找到一个叫 django_migrations 的表。把所有 app 列中值等于你应用名称的那几行删除掉。

然后再执行 makemigrationsmigrate,就能正常工作了。

22

迁移(Migrations)会检查你的模型之间的差异,然后把这些差异转化为一些操作,再把这些操作转成SQL语句。它不会自动把数据库的结构和你的模型同步,而且它也不知道你手动删除了一个表(因为它不知道你做了手动的更改,毕竟,你不应该手动更改。这就是重点)。

那么解决办法是什么呢?手动的更改也需要手动的迁移。你需要做的就是自己写一个迁移文件,手动告诉south去重建这个表。这并不难,文档里讲得很清楚。你只需要做一些像这样的事情:

from django.db import migrations, models

class Migration(migrations.Migration):

    operations = [
        migrations.CreateModel("Foo"),
        migrations.AddField("Foo", "bar", models.IntegerField(default=0))
    ] 

你可以查看第一个迁移文件(就是最开始创建模型的那个),几乎可以直接复制粘贴里面的内容。然后你只需要像往常一样运行这个迁移就可以了。

撰写回答