这是这个问题的延伸:How to move a model between two Django apps (Django 1.7)

我需要把一堆模型从old_app移到new_app.最好的答案似乎是Ozan's,但如果需要外键引用,事情就有点棘手了@halfnibble在对Ozan答案的 comments 中提出了一个解决方案,但我仍然无法确定精确的步骤顺序(例如,何时将模型复制到new_app,何时从old_app中删除模型,哪些迁移将在old_app.migrationsnew_app.migrations中进行,等等)

如有任何帮助,我们将不胜感激!

推荐答案

Migrating a model between apps.

简短的答案是,don't do it!!

但这个答案在现实生活中的项目和生产数据库中很少奏效.因此,我创建了一个sample GitHub repo来演示这个相当复杂的过程.

我正在使用MySQL.(No, those aren't my real credentials).

The Problem

我使用的示例是一个工厂项目,它有一个cars应用程序,最初有一个Car型号和一个Tires型号.

factory
  |_ cars
    |_ Car
    |_ Tires

Car型号与Tires具有ForeignKey关系.(与中一样,您可以通过汽车模型指定轮胎).

然而,我们很快意识到,Tires将是一个拥有自己的视图等的大型模型,因此我们希望它出现在自己的应用程序中.因此,所需的 struct 为:

factory
  |_ cars
    |_ Car
  |_ tires
    |_ Tires

我们需要将ForeignKey关系保持在CarTires之间,因为太多依赖于保存数据.

The Solution

Step 1.设置设计不佳的初始应用程序.

浏览step 1.的代码

Step 2.创建一个管理界面,并添加一组包含ForeignKey关系的数据.

视图step 2.

Step 3.决定将Tires型号转移到自己的应用程序上.一丝不苟地将代码剪切并粘贴到新轮胎应用程序中.确保更新Car模型以指向新的tires.Tires模型.

然后运行./manage.py makemigrations并在某个地方备份数据库(以防出现严重故障).

最后,运行./manage.py migrate并查看Deom的错误消息,

django.db.utils.IntegrityError: (1217, 'Cannot delete or update a parent row: a foreign key constraint fails')

查看到目前为止step 3.年的代码和迁移

Step 4.最棘手的部分.自动生成的迁移看不到您只是将一个模型复制到了不同的应用程序.因此,我们必须做一些事情来补救这一点.

您可以使用step 4.中的注释来跟踪并查看最终的migrations.我测试了一下,以验证它是否正常工作.

首先,我们将在cars上下功夫.您必须进行一次新的空migrations.此迁移实际上需要在最近创建的迁移(执行失败的迁移)之前运行.因此,我对我创建的迁移进行了重新编号,并更改了依赖项,以便首先运行我的自定义迁移,然后为cars个应用程序运行最后一次自动生成的migrations.

您可以使用以下命令创建空迁移:

./manage.py makemigrations --empty cars

Step 4.a.进行自定义old_appmigrations.

在这第一个自定义迁移中,我将只执行"DATABASE_OPERATIONS"migrations.Django为您提供了拆分"状态"和"数据库"操作的选项.您可以通过查看code here来了解这是如何实现的.

在第一步中,我的目标是在不影响Django的状态的情况下将数据库表重命名,从oldapp_model重命名为newapp_model.您必须根据应用程序名称和型号名称计算出Django会给您的数据库表命名什么.

现在,您已经准备好修改最初的tires次migrations.

Step 4.b.修改new_app初始迁移

操作很好,但我们只想修改"状态",而不是数据库.为什么?因为我们保留了cars应用程序中的数据库表.此外,您需要确保之前进行的自定义迁移是此迁移的依赖项.参见轮胎migration file.

因此,现在我们在数据库中将cars.Tires重命名为tires.Tires,并将Django状态更改为识别tires.Tires表.

Step 4.c.修改old_app上次自动生成的migrations.

我们需要修改最后一次自动生成的migrations.它应该需要我们的第一次定制汽车迁移,以及最初的轮胎迁移(我们刚刚修改).

在这里,我们应该保留AlterField操作,因为Car模型is pointing是另一个模型(即使它有相同的数据).然而,我们需要删除DeleteModel的迁移线,因为cars.Tires模型已经不存在了.它已经完全变成了tires.Tires.查看this migration.

Step 4.d.清理old_app中的陈旧模型.

最后但并非最不重要的一点是,您需要在Cars应用程序中进行最终的自定义migrations.在这里,我们将执行"状态"操作,仅删除cars.Tires模型.它是仅状态的,因为cars.Tires的数据库表已经被重命名.这last migration会清理剩下的Django 州.

Database相关问答推荐

使用Postgres获取带有表架构的外键

如何高效地存储棋局?

如何在华为Appcube中创建和使用对象(模型)?

无法向 SiriDB 添加新副本

MySQL 慢查询日志(log) - 慢有多慢?

如何在运行时备份嵌入式 H2 数据库引擎?

如何在数据库中存储具有动态数量属性的数据

C# 连接到数据库并列出数据库

NameError:设置更改为 mysql 后未定义名称_mysql

向表中添加大量索引是否有缺点?

文件访问速度与数据库访问速度

Tornado 的非阻塞 ORM?

在现有数据库上使用 liquibase

我应该在数据库模式中允许空值吗?

PostgreSQL 哈希索引

如何在 Windows 中将用户添加到 PostgreSQL?

MySQL 中 NOW()、SYSDATE() 和 CURRENT_DATE() 之间的区别

CouchDB、MongoDB 和 Redis 中的哪个数据库适合从 Node.js 开始?

标准化人类皮肤 colored颜色 以进行用户交互

从数据库中获取事件