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

Django 1.8: Create initial migrations for existing schema

我启动了一个Django1.8项目,它使用迁移系统。不知怎么的,事情变得一团糟,所以我从数据库中删除了迁移文件夹和表,现在我正试图重建它们,但没有成功。

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

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

  • 清除所有migrations文件夹。完成!
  • django_migrations表中删除所有内容。完成!
  • 为每个应用程序运行python manage.py makemigrations --empty 。完成!
  • 运行python manage.py migrate --fake。完成!(尽管只有在每次执行makemigrations命令后才运行它。
  • 现在我添加了一个新字段,运行makemigrations命令,收到以下错误:django.db.utils.OperationalError: (1054,"Unknown column 'accounts_plan.max_item_size' in 'field list'")

    我在这件事上忙了好几个小时。H**L如何初始化迁移,以便每次都能在不中断迁移的情况下继续工作?

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

    编辑:现在情况变得更糟了。我截断了django_migrations表,删除了所有migrations文件夹。现在我试着运行python manage.py migrate --fake-initial(我在dev文档中发现的东西),它设置了所有django的"内部"应用程序(auth、session等),我得到:(1054,"Unknown column 'name' in 'django_content_type'")。现在,这个"列"不是真正的列。这是django的contenttypes应用程序中定义的@property。这是怎么回事?为什么它将name属性标识为实列?


    最后终于成功了,虽然我不知道为什么,我希望它能在未来发挥作用。在做了大量的试验并通过Django的dev站点(link)之后。以下是步骤(对于遇到此问题的人):

  • 清空django_migrations表:delete from django_migrations;
  • 对于每个应用程序,删除其migrations文件夹:rm -rf /migrations/
  • 重置"内置"应用程序的迁移:python manage.py migrate --fake
  • 对于每个应用程序运行:python manage.py makemigrations 。注意依赖性(具有foreignkey的模型应该在其父模型之后运行)。
  • 最后:python manage.py migrate --fake-initial
  • 在那之后,我运行了最后一个没有--fake-initial标志的命令,只是为了确保。

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

    我相信我不是唯一一个遇到这个问题的人。它必须被更好地记录,甚至简化。

    Django 1.9用户更新:我用django 1.9.4再次遇到了这种情况,第5步失败了。我所要做的就是用--fake替换--fake-initial,使其正常工作。


    Django…,1.8,1.9,…

    您要实现的是压缩现有的迁移并使用替换。

    如何在发布时不使用任何命令(对数据库和同事没有影响的情况)而正确地执行它。

  • 对于每个应用程序,去掉迁移文件夹:mv /migrations/ /migrationsOLD/

  • 对于每个应用程序运行:python manage.py makemigrations

  • 自定义每个新迁移:

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

      0002_initial2.py中准备第二次空移植(对app_other::0001_initial.py的依赖关系:0001_initial.py以及所有foreignkey、M2M,与其他应用程序在0001移植步骤中创建的模型相关)

      一切都必须井然有序——有时需要更多的迁移来准备。在每次迁移中都要注意这里的dependencies属性。

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

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

    • 在新的迁移类中添加replaces属性。(就像自己的习俗一样,一个江户一〔28〕)。把所有来自江户的旧移民都放在那里。
  • makemigrations验证所有内容。

    断言"未检测到更改"

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

    断言相似:

    [X]0001_首字母

    [X]0002_首字母2(102次挤压迁移)

  • 例子:

    老年人:

    1
    2
    3
    4
    0001_initial.py
    0002_auto.py
    ...
    0103_auto.py

    准备:

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

    replaces中加上最后一个(这里的0002,可以是0001):

    1
    replaces = [(b'', '0002_auto.py'), ..., (b'', '0103_auto.py')]

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

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


    我遇到过这种情况,但我从来没有必要删除数据库来解决它。通常,我会从应用程序中删除migration s文件夹,然后从数据库中删除迁移条目。

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

    另外,我通常只运行python manage.py makemigrations,然后只运行python manage.py migrate,即使在初始迁移时,它也可以与django 1.7和1.8一起工作。


    如果您使用路由器,可能存在问题。检查方法allow_migrate是否在routers.py中正确执行。尽量将返回值设置为True,检查是否能解决问题。

    1
    2
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        return True

    谢谢-我已经研究这个问题一段时间了,你的最佳实践列表真的很方便。这可能有助于像我这样的Python新手:

    如果您从现有的一组模型开始,请清除以前进行的任何迁移!

    我的情况是,我开始使用sqlite只是为了了解django,然后切换到一个mysql数据库-它不断抛出1053错误,可能试图应用以前的迁移,它没有解决的资源…