在本文中, 将会介绍Django-south的基本概念和基本用法, 帮助Django开发人员简化数据迁移的过程. 在django-admin命令中有syncdb指令, 其目的是根据model.py建立相应的数据库表. 但咱们在开发的过程当中, 常常会须要更改model, 删除或者增长Field, 这时, syncsb命令就不那么好用了, 由于syncsb没法自动更改数据库表结构. 所以, 咱们时常须要手动删除数据库表, 再运行syncdb.
python
而有了south后, 状况就不一样了. south为django带来了数据迁移功能, 它的主要目的是为django应用程序带来一个简单, 稳定, 与数据库管理系统无关的迁移层, 用来自动处理django中的数据表变化. 使用south提提供的工具, 你能够在不一样版本的数据库结构中来回迁移,数据库
south刚出来时只是一个相对无名的数据库迁移应用. 但渐渐地它成为了django中最为流行和广泛使用的数据迁移工具. 而且在django 1.7发布时, 数据迁移功能将会被整合到django中, 其提供的django-admin migrate也将代替syncdb命令. 所以, 咱们不得不了解一下south的魅力所在.django
安装south的方式有许多中, 包括从pip安装, 直接使用south的Mercurial库安装, 或从操做系统自带的软件库中安装. 推荐使用pip, 将south安装到VirtualEnv中:app
pip install South
而后在django的'south'添加到setting.py的INSTALLED_APPS中, 并运行syncdb, 建立south所须要的数据表:工具
./manage.py syncdb
首先咱们介绍在新app中使用south. 须要注意的是, south的迁移记录文件是储存在每一个app下的migrations目录中的, 若是该app没有建立任何migrations, 那么该app仍是经过syncdb来管理的.ui
建立新app, 并将其添加到INSTALLED_APPS中:this
./manage.py startapp southtut
打开该app的model.py, 建立model:spa
from django.db import modelsclass Knight(models.Model): name = models.CharField(max_length=100) of_the_round_table = models.BooleanField()
south提供了多种创建迁移记录的方式, 有些是自动的, 有些是手动的. 而用的最多的可能就是--auto和--initial这两种自动建立的方式了.操作系统
--auto是根据以前的迁移记录, 与当前model做比较, 而后自动建立新的迁移记录. 例如当添加了一个新field时, --auto会注意到, 并自动生成添加了新栏的迁移记录.code
你会注意到, --auto须要上一次的迁移记录才能建立新的迁移记录. 而--initial则能够用来为model中全部的表建立初始的迁移记录. 所以, 先使用--initial初始化迁移记录, 而后在model有所变更后, 使用--auto自动生成迁移记录
使用--initial为咱们新建的app southtut建立初始迁移记录:
$ ./manage.py schemamigration southtut --initialCreating migrations directory at '/home/andrew/Programs/litret/southtut/migrations'...Creating __init__.py in '/home/andrew/Programs/litret/southtut/migrations'... + Added model southtut.KnightCreated 0001_initial.py. You can now apply this migration with: ./manage.py migrate southtut
此时, 在southtut的migrations下就自动生成reated 0001_initial.py文件, 这就是第一个迁移记录文件. 注意, 此时打开MySQL或PostreSQL, 你会发现没有名为southtut_knight的数据表, 由于数据库中的数据表并无变化(未建立也未修改), 咱们须要用到migrate命令来完成这一步:
$ ./manage.py migrate southtutRunning migrations for southtut:- Migrating forwards to 0001_initial.> southtut:0001_initial- Loading initial data for southtut.
此时再打开MySQL或PostgreSQL, southtut_knight数据表已经建立好了. 但到如今为止, 这些功能都是sync能实现的. 接下来咱们修改Knight model, 增长一个field:
from django.db import modelsclass Knight(models.Model): name = models.CharField(max_length=100) of_the_round_table = models.BooleanField() dances_whenever_able = models.BooleanField()
此时若是使用syncsb, 则django没法为你增长dances_whenever_able列, 所以, 咱们使用south:
$ ./manage.py schemamigration southtut --auto+ Added field dances_whenever_able on southtut.KnightCreated 0002_auto__add_field_knight_dances_whenever_able.py. You can now apply this migration with: ./manage.py migrate southtut
从输出的提示能够看到, south已经为你增长了新的迁移记录文件(0002_auto__add_field_knight_dances_whenever_able.py), south的命名方式是序列号+所作的更改. 接下来, 咱们根据提示, 使用migrate命令修改数据库:
$ ./manage.py migrate southtutRunning migrations for southtut:- Migrating forwards to 0002_auto__add_field_knight_dances_whenever_able.> southtut:0002_auto__add_field_knight_dances_whenever_able- Loading initial data for southtut.
当修改model时, 建立没有默认值(default)的field后:
from django.db import modelsclass Knight(models.Model): name = models.CharField(max_length=100) of_the_round_table = models.BooleanField() dances_whenever_able = models.BooleanField() shrubberies = models.IntegerField(null=False)
此时再执行schemamigration, 会出现一些没有见过的选择:
./manage.py schemamigration southtut --auto ? The field 'Knight.shrubberies' does not have a default specified, yet is NOT NULL. ? Since you are adding or removing this field, you MUST specify a default ? value to use for existing rows. Would you like to: ? 1. Quit now, and add a default to the field in models.py ? 2. Specify a one-off value to use for existing columns now ? Please select a choice:
其中选项1意思是, 放弃本次自动迁移, 并退出, 你能够在field中添加default值后再执行schemamigration. 选项2的意思是, 为已经存在的行添加一个一次性的值. 当你选择2时, 会出现python提示行, 你可使用python的datetime模块:
? Please select a choice: 2 ? Please enter Python code for your one-off default value. ? The datetime module is available, so you can do e.g. datetime.date.today() >>> 0 + Added field shrubberies on southtut.KnightCreated 0003_auto__add_field_knight_shrubberies.py. You can now apply this migration with: ./manage.py migrate southtut
此时你能够查看自动生成的迁移记录文件, south会为新建的栏添加默认值0, 这样数据库才不会报错. 而后咱们再执行migrate:
$ ./manage.py migrate southtut Running migrations for southtut: - Migrating forwards to 0003_auto__add_field_knight_shrubberies. > southtut:0003_auto__add_field_knight_shrubberies - Loading initial data for southtut.mou