Django支持ORM模型,我们不必写一条SQL语句,就可以方便使用面向对象管理数据库。数据库的管理可以分为结构迁移和数据迁移。
结构迁移是只是指表的结构改变。我们只需要修改Django的数据模型,然后用python manage.py makemigrations
自动生成需要执行的数据迁移代码(一般保存在app/migrations
文件夹下),然后用python manage.py migrate
执行代码,就可以将变化应用到数据库。
另一种是数据迁移。之前我的做法是,写一个url映射到view,在view中写操作数据库的代码。执行完毕后删掉url。这样做有很多坏处:
- 将操作数据库开放了(即使可以写管理员权限)
- 污染url和view的代码
- 不能将所有有关数据库管理的代码放下
migrations
下面
好处是,如果常用的话,可以作为管理员“维护数据库”的一种方式。但如果是这种用途的话,还是写成一个中规中矩的view比较好。
其实,Django本身就有数据迁移的功能,上面这种做法太“歪门邪道”了。
数据迁移和结构迁移类似,只不过Django不是直接为你生成迁移结构的代码,而是生成一个框架,然后你在这个框架根绝自己的需要写代码。其实这个样子更灵活。
1.生成数据迁移的空白文件
执行下面的命令,生成一个迁移的脚本,等着你填上需要执行的命令。
1 |
python manage.py makemigrations --empty yourappname |
生成的空白文件,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# -*- coding: utf-8 -*- # Generated by Django A.B on YYYY-MM-DD HH:MM from __future__ import unicode_literals from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [ ('yourappname', '0001_initial'), ] operations = [ ] |
2.填写数据迁移代码
文件中的Operations是空着的,这个地方是需要执行的数据迁移操作。数据操作可以写成函数,然后在Operations里面用RunPython运行函数。
函数的第一个变量是app,第二个是SchemaEditor,可以用来手动修改数据表的结构。不过不推荐这样做,做自动迁移的时候可能遇到问题。
下面这个迁移是自动根据以前名字的firstname和lastname生成name。导入模型的方式有点特殊,将要做的操作写到Python函数里面,然后在Operations里运行Python函数。除了RunPython之外,也可以RunSQL等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models def combine_names(apps, schema_editor): # 这里不能直接导入Person模型,因为这里的模型要求是特定的一个版本 # 如果直接导入,就会是最新的版本了 Person = apps.get_model("yourappname", "Person") for person in Person.objects.all(): person.name = "%s %s" % (person.first_name, person.last_name) person.save() class Migration(migrations.Migration): initial = True dependencies = [ ('yourappname', '0001_initial'), ] operations = [ migrations.RunPython(combine_names), ] |
3.执行migrate命令,应用数据迁移
和应用结构迁移一样,执行下面的命令就可以了。
1 |
python manage.py migrate |
4.使用其他app里面的Model
如果RunPython函数里面用到别的app(不是此migrations存在的app)里面的model,应该在Dependencies里面模仿例子加上别的app的名字以及最新的migrations依赖。
否则,使用apps.get_model()
的时候,会遇到LookupError: No installed app with label 'myappname'
。
下例,app1里面的migrations
用到了app2的Model。
1 2 3 4 5 6 7 8 9 10 11 |
class Migration(migrations.Migration): dependencies = [ ('app1', '0001_initial'), # 加入app名字,和最后的migrations ('app2', '0004_foobar'), ] operations = [ migrations.RunPython(move_m1), ] |
Pingback: 关于Django迁移操作的一些说明 – 小舟从此逝,江海寄余生。