【现象】
https://www.jianshu.com/p/8d0463e25f35
终极方式是备份数据库删除原来的,创建一个空的再来migrate,随后还原数据,步骤如下:
mysqldump -uroot -pIotos12345678 iotos_paas > iotos_paas.sql mysql>drop database iotos_paas; mysql>create database iotos_paas;
1)一般情况下,我们是这样逐个操作(在各个应用下都没有此前生成的migrations目录文件时)
手动:iot、account、drive、video、margin、alert、scada
python3 makemigrations xxx; python3 migrate xxx;
自动:admin、auth、contenttypes、sessions,
python3 makemigrations; python3 migrate;
但是实际反而这种操作,导致数据库表字段ORM有整改变动,反而django mirgate出各种错!
2)实际测试发现,iotos-paas-v2中,从空数据库构建完整数据库表结构ORM,全局操作即可(在各个应用下已经有了此前生成的migrations目录文件时):
(或者指定某个应用比如account,效果也是一样的)
然后验证数据库中指定表的某个字段是否如期创建:describe iotos_paas.scada_scada;
修改了某个表结构或字段增改,比如scada_scada表,也只需要全局migrate即可,不需要指定特定Django App:
mysql -uroot -pIotos12345678 iotos_paas < iotos_paas.sql;
【重要】找到了Django ORM migrate经常失败,提示数据库XXX表已存在的根本原因了!!
分为几种情况:
以下全局操作migrate即可,表都会自动生成,不再需要每个APP单独migrate,因为里面migrations目录都在,直接操作全局的就好:
mysql还原sql导入到数据库非空时,对此前的migrations基础上migrate会报错,提示xxx表已存在,去掉一个还有一个,所有表都报已存在!!
全局migrate无错误提示,但是没有任何效果(绿色ok);针对具体APP来migrate,提示相应APP的XX表已存在!
全局migrate报错,提示要基于APP进行migrate;逐个APPmigrate生成没问题!
【方案一】保持表结构能migrate,并且导入的数据只有当前修改了表结构的才会清空,其他都保留在
【附】Django项目的APP下面的migrations目录非常重要,不是临时文件!如果随意删除或者git没有同步,拉取下来想要在mirgate,就会一堆报错和坑!
https://www.kawabangga.com/posts/1789
Django的Model是按照每次的migrations管理(即app下的migrations包)的。每次更新Model之后,都需要先运行python manage.py makemigrations进行生成migration,这些migrations中记录了数据库的变更,然后用python manage.py migrate应用这些更改。
随着项目的增大,migrations也越来越多,每次新的migration都是基于前一次的,也就是说,每次更改数据库,都要把所有的migration走一遍。导致执行migrate的时候速度很慢。比如我们公司的仓库,每次migrate需要二十多分钟。大哥说可以删掉所有的migrations,重新生成,然后用migrate –fake命令“假装执行”,这样做一次,后面的操作都变快了。
今天,我想在自己的项目上用这个方法,于是照着大哥的方法做了遍。本地没有任何问题,做好之后,去服务器操作。结果挂了。服务器的错误如下:
试过很多办法,甚至把本地的数据库都删掉,也无济于事。
其中的一个尝试让我发现,服务器revert回去,先执行makemigrations,服务器没问题,然后git拉到本地,本地竟然出现了同样的问题。
尼玛,坑爹呢这是。
我打开migrations文件,看了看有个叫做('auth', '0008_auto_20160710_0926')的依赖,本地找不到。在项目里面全局搜了一下,也没搜到这个文件。
最后用pycharm全局搜了一下,找到了…… 从pycharm的颜色可以看出,这并不是在项目中的一个文件,而是site-package的文件,竟然也有migrations,好坑啊……
从git diff可以看出,主要是文件名字的结尾不同。django生成migrations文件的明明规则是次数+内容+时间的。这个不同得从我管理项目的方式说起。我觉得migrations文件不是项目代码的一部分(不是自动生成的),所以将migrations文件夹放到了gitignore中。每次更新数据库,本地做本地的migrations,服务器做服务器的。这样,就造成时间不同,本地是09:26,服务器是10:04,两个文件名字不一样……所以有了上文的冲突。
比较好的解决方法是:用git连migrations一起管理着,服务器只执行migrate。说不定什么时候我们还需要手动修改生成的migrations呢!
瞎忙活了一下午,给我的教训是……不要手忙脚乱,认真看报错的信息,慢慢推理吧!慌什么呢!
教训2:还是实践让人学习啊,应该用git管理migrations而不是教给django去生成就行了。
【方案二】(终极方案)导入进来的数据和表结构都在,并且能后续migrate修改表结构(新增字段可以、修改字段名称发现不起效果)
不仅仅是解决数据库备份还原导入后无法migrate,同时也是解决任何时候mirgate报错的恢复机制!
https://zhuanlan.zhihu.com/p/55440044
默认此时已经mysql导入了sql覆盖还原了数据库,现在开始
这里可以看到项目本身的应用:iot、account、drive、video、margin、alert、scada,只要有migrations目录的都会列出来,此外还有django内部的app,比如这里admin!且其migrations目录在django的安装包目录里!问题隐藏非常深,并不在项目目录!
python3 manage.py showmigrations
所有APP都经过这些步骤后,就可以全局mirage了:
以scada为例,本地原始数据库ORM字段结构,并且按照这个结构在平台有导出数据,同时现在对原始ORM结构有修改,包括修改了某个字段名、新增了某个字段。
mysql把前面导出的数据还原,并且经过本方案二做到可以migrate同时不丢失数据。只是初始的这个makemigrations、migrate,并不会把scada本地更新后的ORM同步上去,还是旧的,看着好像没变!
实际上,需要对ORM文件再做修改,才能被识别有变动,再进行全局makemigratioins和migrate,就可以新增、修改以及删除字段,包括批量新增、批量修改、批量删除都可以!