在本文中, 將會介紹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