Django 1.8:为现有架构创建初始迁移


74

我开始了一个使用迁移系统的django 1.8项目。
事情变得一团糟,所以我从数据库中删除了迁移文件夹和表,现在我试图重建它们,但没有成功。

我有三个应用程序(3个models.py文件),并且模型完全反映了表格!

到目前为止,我发现的最佳方法是:

  1. 删除所有migrations文件夹。做完了!
  2. django_migrations表中删除所有内容。做完了!
  3. python manage.py makemigrations --empty <app>为每个应用程序运行。做完了!
  4. 运行python manage.py migrate --fake。做完了!(尽管只有在每个makemigrations命令之后都运行它,它才有效。

现在,我添加一个新字段,运行makemigrations命令,并且收到以下错误:
django.db.utils.OperationalError: (1054, "Unknown column 'accounts_plan.max_item_size' in 'field list'")

我在这件事上花了HOURS。如何初始化迁移,以便每次都能继续工作而不会中断迁移?

为什么这么复杂?为什么没有一个简单的单线:initiate_migrations_from_schema

编辑:
现在事情变得更糟了。我删节了django_migrations表并删除了所有migrations文件夹。
现在,我尝试运行python manage.py migrate --fake-initial(我在DEV文档中找到的东西),只是这样它设置了Django的所有“内部”应用程序(身份验证,会话等),并且我得到了:
(1054, "Unknown column 'name' in 'django_content_type'")
现在,这个“列”不是一个真实的列。这是@propertyDjangocontenttypes应用程序中定义的。这里发生了什么?为什么将name属性标识为真实列?


您是否删除了实际表?还是只是将其清空?
rnevius 2015年

我只是将其清空:delete from django_migrations
user1102018 2015年

您可能需要删除所有表格,而不仅仅是清空它们
rnevius 2015年

我在这些表中有数据,但我不想删除它们。我知道我可以备份,删除,创建和还原数据。但是我有10张桌子,我不想这么做。我只想启动迁移。
user1102018 2015年

Answers:


168

终于让它工作了,虽然我不知道为什么,但我希望它将来能工作。
经过无数次尝试并经过Django的开发站点(链接)。
这是步骤(针对遇到此问题的人员):

  1. 清空django_migrations表格:delete from django_migrations;
  2. 对于每个应用程序,删除其migrations文件夹:rm -rf <app>/migrations/
  3. 重置“内置”应用的迁移: python manage.py migrate --fake
  4. 对于每个运行的应用:python manage.py makemigrations <app>。注意相关性(带有ForeignKey的模型应在其父模型之后运行)。
  5. 最后: python manage.py migrate --fake-initial

在那之后,我运行了没有--fake-initial标志的最后一个命令,只是为了确保。

现在一切正常,我可以正常使用迁移系统。

我确定我不是唯一遇到此问题的人。必须对其进行更好的记录,甚至简化。

针对Django 1.9用户的更新:
我再次使用Django 1.9.4遇到这种情况,而第5步失败。
所有我必须做的是替换--fake-initial--fake,以使其正常工作。


不过,我正在RuntimeError: Error creating new content types. Please make sure contenttypes is migrated before trying to migrate apps individually.达到Django 1.8.3的最后一步。你知道为什么吗?
ericn

1
@eric尝试python manage.py migrate contenttypes在最后一步之前运行。
杜鹃花

9
应该记录在“如何重置迁移”下。甚至还可以使用reset_migrations管理命令-Adam
Spence,

谢谢你,我在其他地方找不到如何做的……这确实应该记录在案。
Hayze

必须从django_migrations中删除;然后运行python manage.py migration。而且有效。
Stryker

3

django ...,1.8,1.9,...

您想要实现的是压缩现有迁移并对其进行替换。

发布时如何在不使用任何命令的情况下正确执行此操作(这种情况不会影响数据库和同事)。

  1. 对于每个应用,摆脱其迁移文件夹: mv <app>/migrations/ <app>/migrationsOLD/

  2. 对于每个运行的应用程序:python manage.py makemigrations <app>

  3. 自定义每个新迁移:

    • 如果您有一个复杂的应用程序,或者它们之间有多个应用程序和相关模型,请避免CircularDependencyErrorValueError: Unhandled pending operations for models

      准备第二次空迁移<app> 0002_initial2.py(将依赖项放入app_other::0001_initial.py<app>::0001_initial.py以及-所有ForeignKey的,M2M涉及到在0001创建的模型迁移步骤在其他应用程序)

      一切必须井井有条-有时它将需要更多的迁移才能准备。dependencies在每个迁移中,请注意此处的属性。

    • 注意初始值-验证自己的所有RunPython操作,migrationsOLD并在需要时将代码复制到新的初始迁移中。

    • (可选--fake-initial)添加initial=True到所有新的迁移类(如果添加了,也添加0002)。

    • replaces在新的迁移类中添加属性。(例如自己的自定义a squashmigrations)。将所有来自<app>
  4. 使用验证所有内容makemigrations

    断言“未检测到更改”

  5. 检查是否migrate -l到处显示[x]

    断言类似:

    [X] 0001_initial

    [X] 0002_initial2(102个压缩的迁移)

例:

对于旧的:

0001_initial.py
0002_auto.py
...
0103_auto.py

准备:

0001_initial.py
0002_initial2.py  (optional but sometimes required to satisfy dependency)

并添加到replaces最后一个(此处为0002,可以为0001):

replaces = [(b'<app>', '0002_auto.py'), ..., (b'<app>', '0103_auto.py')]

0001_initial.py的命名方式应与旧名称相同。

0002_initial2.py是新的,但它替代了旧的迁移,因此Django会将其视为已加载。


2

我已经遇到过这种情况,但是我从来不需要删除数据库来解决它。通常,我从应用程序中删除迁移文件夹,然后从数据库中删除迁移条目。

我会尝试一次运行一次迁移。如果应用程序中的任何一个依赖于其他表,则显然要最后添加它们。

此外,我通常只是运行,蟒蛇manage.py makemigrations然后就蟒蛇manage.py迁移 即使初始迁移它应该很好地工作的Django 1.7和1.8。


4
尝试了一下,它显然不起作用,因为该migrate命令尝试创建表(已经存在)...
user1102018

你能尝试>> python makemigrations yourApp --initial
克里斯·霍克斯

试了一下,得到了: manage.py makemigrations: error: unrecognized arguments: --initial
user1102018 2015年

0

如果您使用的是路由器,则可能是一个问题。检查方法allow_migrate是否在中正确执行routers.py。尝试将返回值始终设置为True,并检查其是否可以解决问题,

def allow_migrate(self, db, app_label, model_name=None, **hints):
    return True
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.