良好的重构是项目可持续的一个重要因素。最近开始花时间重构「奇点」的网站部分,其中一个任务就是把 Django 项目的 Model 以及数据库进行迁移和合并,今天实践了一把,很成功,写文章纪录一下。
什么是「App Model 迁移」,简单地说,一个 Django 项目可能存在不同的 App,随着项目的发展,或者早先错误的规划,需要重新调整一下项目结构,比如把 App 们合并起来,把 App B 的东西合并至 App A,这就涉及到了 Model 和数据库的迁移。
如何进行无痛的 App Model 迁移呢?涉及到代码层面的可能还比较方便,但是已经存在的数据如何用正确地方式去迁移,这就是一个问题了。在参考了 StackoverFlow 上的一个回答后(How to move a model between two Django apps),我成功地在我的 Django 2.0 项目上完成了 Model 和已有数据的迁移。
先来看看操作前的 PostgreSQL 的数据表结构,除去 Django 内置的 Model,你可以从这个数据表结构里看到,我有两个 Django App,分别是 jidian 和 weibo。我要做的事情就是,在 Django 项目结构上,把 weibo 的代码合并进 jidian,同时把数据库也做相应的变化。
根据 How to move a model between two Django apps 这个答案,一步步操作下来,就可以顺利完成。
第一步:手动创建 weibo 至 jidian 的 Migration
在终端执行,手动创建一个 weibo 的 migration,这一步操作的意思是,把 weibo 的数据库结构修改成以 jidian 为名的。
python manage.py makemigrations weibo --empty
源码:
# Generated by Django 2.0.4 on 2018-04-12 03:06
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('weibo', '0007_weibouser_task_schedule_date'),
]
database_operations = [
migrations.AlterModelTable('Subscription', 'jidian_subscription'),
migrations.AlterModelTable('WeiboStatus', 'jidian_weibostatus'),
migrations.AlterModelTable('WeiboUser', 'jidian_weibouser')
]
state_operations = [
migrations.DeleteModel('Subscription'),
migrations.DeleteModel('WeiboStatus'),
migrations.DeleteModel('WeiboUser')
]
operations = [
migrations.SeparateDatabaseAndState(
database_operations=database_operations,
state_operations=state_operations)
]
第二步: jidian 接收来自 weibo 的 Migration
在 jidian 这个 App 里,创建好和 weibo 里一模一样的 Model,准备好接收(注意这会不要删除 weibo 的东西,也不要从 INSTALLED_APPS 里移掉它。
创建好文件后, 终端运行以下指令,会自动生成一个待接受的 migration:
python manage.py makemigrations jidian
然后,对自动生成的 Migration 稍作修改,把 operations 改成 state_operations,并增加一个真正的 operations。
operations = [
migrations.SeparateDatabaseAndState(state_operations=state_operations)
]
关于这些操作的真正含义,可以见文档,我也是一知半解,所以就不多说了:https://docs.djangoproject.com/zh-hans/2.0/ref/migration-operations/
第三步:Do Migration
所有的东西都 Ready 了,这时开始真正的 Migration 步骤:
python manager.py migrate
如果一切正常的话,这个时候数据表就会成功修改,App 和 Model 也将工作一致。成功地把两个 App 合并起来了:
总结
借用 Web 框架自带的机制去做这个操作,不要手动去改数据库文件,可以自动化检查,并且保证所有的东西仍然继续工作。