Django 1.7迁移不重新创建已删除的表,为什么?
我在使用Django 1.7的迁移功能。
我不小心把数据库中的一个表删掉了。我以为重新运行迁移就能把这个表重新创建出来,但结果并不是这样,Django提示说“没有迁移可以应用”。
我该怎么做才能让Django重新创建这个表呢?
我已经运行了:
> makemigrations - No changes detected
> migrate - No migrations to apply.
我尝试对模型做了一些修改,然后运行新的迁移,但系统只是提示“表'x.test_customer'不存在”,这确实是对的,但我希望的是它能重新创建这个表。
10 个回答
在我的情况下,使用的是 django 2.0.2
,为了重新创建被删除的表,我需要先把 myapp
中的模型注释掉,然后用 --fake
进行迁移,接着再把模型取消注释,并且进行不带 --fake
的迁移。这个过程和raul的回答稍有不同:
- 删除你想要的应用中的迁移文件。
- 根据raul的回答:在数据库中执行
DELETE FROM django_migrations WHERE app = 'app_name'
。 - 在
models.py
中注释掉代码,以及在views
、signals
等地方使用这些模型的代码(这样可以避免错误)。 - 运行
python manage.py makemigrations YOUR_APP_NAME
。 - 运行
python manage.py migrate --fake
。 - 取消注释在第3步中注释掉的内容。
- 再次运行
python manage.py makemigrations YOUR_APP_NAME
。 - 进行不带 --fake 的迁移:运行
python manage.py migrate
。
这样应该能解决一些用户的问题。
我其实找到了一种更简单的方法来解决这个问题。你可以假装撤销那些并不存在的东西,然后再重新迁移。如果你的迁移文件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
这样应该也没问题了!
我找到的另一个解决方案,效果非常好:
在 Django 1.7 版本中:
删除你的迁移文件夹
在数据库中执行:
DELETE FROM django_migrations WHERE app = 'app_name'
。你也可以选择直接清空这个表。
运行
python manage.py makemigrations
运行
python manage.py migrate --fake
在 Django 1.9.5 版本中:
删除你的迁移文件夹
在数据库中执行:
DELETE FROM django_migrations WHERE app = 'app_name'
。你也可以选择直接清空这个表。
运行
python manage.py makemigrations app_name
运行
python manage.py migrate
这个方法对我来说效果百分之百好用!
去你的数据库里,找到一个叫 django_migrations
的表。把所有 app
列中值等于你应用名称的那几行删除掉。
然后再执行 makemigrations
和 migrate
,就能正常工作了。
迁移(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))
]
你可以查看第一个迁移文件(就是最开始创建模型的那个),几乎可以直接复制粘贴里面的内容。然后你只需要像往常一样运行这个迁移就可以了。