Django支持ORM模型,我们不必写一条SQL语句,就可以方便使用面向对象管理数据库。数据库的管理可以分为结构迁移和数据迁移。

结构迁移是只是指表的结构改变。我们只需要修改Django的数据模型,然后用python manage.py makemigrations自动生成需要执行的数据迁移代码(一般保存在app/migrations文件夹下),然后用python manage.py migrate执行代码,就可以将变化应用到数据库。

另一种是数据迁移。之前我的做法是,写一个url映射到view,在view中写操作数据库的代码。执行完毕后删掉url。这样做有很多坏处:

  1. 将操作数据库开放了(即使可以写管理员权限)
  2. 污染url和view的代码
  3. 不能将所有有关数据库管理的代码放下migrations下面

好处是,如果常用的话,可以作为管理员“维护数据库”的一种方式。但如果是这种用途的话,还是写成一个中规中矩的view比较好。

其实,Django本身就有数据迁移的功能,上面这种做法太“歪门邪道”了。

数据迁移和结构迁移类似,只不过Django不是直接为你生成迁移结构的代码,而是生成一个框架,然后你在这个框架根绝自己的需要写代码。其实这个样子更灵活。

1.生成数据迁移的空白文件

执行下面的命令,生成一个迁移的脚本,等着你填上需要执行的命令。

空白迁移脚本命令

Shell

1

python manage.py makemigrations --empty yourappname

生成的空白文件,如下所示。

Python

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等等。

Python

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命令,应用数据迁移

和应用结构迁移一样,执行下面的命令就可以了。

migrate

Python

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。

dependencies

Python

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),

    ]

5.参考资料

  1. Django文档,Migrations