首页 文章

Django 1.8:为现有模式创建初始迁移

提问于
浏览
65

我启动了一个使用迁移系统的django 1.8项目 .
在某种程度上事情变得混乱,所以我从数据库中删除了迁移文件夹和表,现在我正在尝试重建它们,但没有成功 .

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

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

  • 删除所有 migrations 文件夹 . 完成!

  • 删除 django_migrations 表中的所有内容 . 完成!

  • 为每个应用运行 python manage.py makemigrations --empty <app> . 完成!

  • 运行 python manage.py migrate --fake . 完成! (虽然只有在每次 makemigrations 命令之后运行它才有效 .

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

我一直在烧这个东西 . 我怎样才能初始化迁移,这样我每次都可以继续工作而不会发生迁移中断?

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

编辑:
现在事情变得更加糟糕了 . 我截断了 django_migrations 表并删除了所有 migrations 文件夹 .
现在我尝试运行 python manage.py migrate --fake-initial (我在DEV文档中找到的东西),只是因此它设置了所有Django 's ' internal ' apps (auth, session, etc) and I' m得到:
(1054, "Unknown column 'name' in 'django_content_type'") .
现在,这个"column"不是真正的专栏 . 这是在Django的 contenttypes app中定义的 @property . 这里发生了什么?为什么将 name 属性标识为真正的列?

6 回答

  • -1

    如果在升级到Django 1.8时仍然出现此错误,请确保为应用程序所依赖的第三方应用程序执行makemigrations并单独迁移 .

  • 152

    最后让它工作,虽然我不知道为什么,我希望它将来会有用 .
    经过多次试验并经过Django的开发站点(link) .
    以下是步骤(对于遇到此问题的人):

    • 清空 django_migrations 表: delete from django_migrations;

    • 对于每个应用,删除其 migrations 文件夹: rm -rf <app>/migrations/

    • 重置"built-in"应用的迁移: python manage.py migrate --fake

    • 对于每个应用程序运行: python manage.py makemigrations <app> . 处理依赖关系(具有ForeignKey的模型应该在其父模型之后运行) .

    • 最后: python manage.py migrate --fake-initial

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

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

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

    Update for Django 1.9 users:
    我用Django 1.9.4再次出现了这个场景,第5步失败了 .
    我所要做的就是将 --fake-initial 替换为 --fake 以使其正常工作 .

  • 2

    我遇到过这种情况,但我从来没有丢弃数据库来解决它 . 通常,我从应用程序中删除迁移文件夹,并从数据库中删除迁移条目 .

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

    此外,我通常只是运行, python manage.py makemigrations 然后只是 python manage.py migrate 即使初始迁移它应该可以正常使用Django 1.7和1.8 .

  • 0

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

    您想要实现的目标是压缩现有迁移并使用替换它们 .

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

    • 对于每个应用,请删除其迁移文件夹: mv <app>/migrations/ <app>/migrationsOLD/

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

    • 自定义每个新迁移:

    • 如果您之间有 complex app 或更多应用及相关模型,请避免 CircularDependencyErrorValueError: Unhandled pending operations for models

    准备 <app> 0002_initial2.py 中的第二个空迁移(将依赖项放在 app_other::0001_initial.py<app> :: 0001_initial.py 上 - 所有ForeignKey,M2M与其他应用程序中的0001迁移步骤中创建的模型相关)

    一切都必须井然有序 - 有时需要更多的迁移准备 . 在每次迁移中处理 dependencies 属性 .

    • 负责初始值 - 验证 migrationsOLD 中的所有 RunPython 操作,并在需要时将代码复制到新的初始迁移 .

    • --fake-initial 的可选项)将 initial=True 添加到所有新的迁移类中(如果已添加,则为0002) .

    • 在新的迁移类中添加 replaces 属性 . (比如自己定制 squashmigrations ) . 把所有旧的迁移放在 <app>

    • 使用 makemigrations 验证所有内容 .

    断言“未检测到任何变化”

    • 检查 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会将其视为已加载 .

  • -3

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

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

    谢谢 - 我一直在研究这个问题,你的最佳实践列表非常方便 . 这可能有助于新手像我这样的python:

    If you're starting with an existing set of models, clear any previous migrations you have made!

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

相关问题