django 資料庫增強工具 south 的安裝使用和注意事項。。。
此時,使用 south 可以達到 修改 models 的時候, 自動更改資料庫表結構。
south的安裝
安裝 south 很簡單
pip install south
新增 south 到專案中
對於 新增 south 到專案中,主要有三種情況。參考 stackoverflow 上的總結 如下:
1)建立一個沒有資料庫的新專案時
1、建立資料庫 ,將south新增到INSTALLED_APPS
2、執行syncdb命令,它將django和south的資料表加入到資料庫中。每次執行 syncdb 之後,都執行 python manage.py migrate 進行一次
3、然後將你建立的apps新增到 INSTALLED_APPS
5、對每個app分別執行 “python manage.py schemamigration app_name --initial”,它將在每個app的目錄下建立migration目錄和相應的檔案。
6、然後執行“python manage.py migrate app_name”,這一步將app的資料表加入到資料庫中
2)在帶有資料庫的已存專案中使用south
1、將south加入到INSTALLED_APPS中
2、執行syncdb,它將south的資料表加入到資料庫中
3、對每個app分別執行python manage.py schemamigration app_name --initial,它將在每個app的目錄下建立migration目錄和相應的檔案
4、對每個app分別執行“python manage.py migrate app_name 0001 --fake”,該命令不會對資料庫做任何操作,只是欺騙一下south,讓它在south_migrationhistory表中新增一些記錄以便於下次你想創造migration檔案的時候所有東西都已搞定。
3、在沒有資料庫的已存專案中使用south
1)建立資料庫
2)將south加入到INSTALLED_APPS中
3)對每個app分別執行“ python manage.py schemamigration app_name --initial”,它將在每個app的目錄下建立migration目錄和相應的檔案
4)執行syncdb,它將所有沒有migrations的apps加入到資料庫中
5)然後執行“python manage.py migrate”命令,它將對你的所有apps執行遷移操作。
使用 south
安裝遷移 south 之後,就是使用。主要有兩個命令
每次更改 models 之後執行
python manage.py schemamigration app_name --auto
會看到 model 修改了那些屬性
然後執行
python manage.py migrate app_name
會將更改同步到資料庫中
實戰
增加一個欄位
例如我的 初始 model 如下
class User(models.Model): username = models.CharField(max_length=20, unique=True) password = models.CharField(max_length=40) email = models.EmailField(max_length=80, unique=True)
此時需要新增一個 test 欄位 ,更改 model 如下
class User(models.Model):
username = models.CharField(max_length=20, unique=True)
password = models.CharField(max_length=40)
email = models.EmailField(max_length=80, unique=True)
test = models.CharField(max_length=10)
更改之後執行
python manage.py schemamigration app_name --auto
1 .此時會有兩種情況,如果資料庫本身沒有記錄,就直接執行結束。這種情況比較少見.
2 第二種情況是資料表已經存在記錄。比如我存在一條記錄 usname= rsj217 password=111 [email protected] 會出現下面這個
(pythonenv)[email protected]:~/project/python/vitrual/dblog$ python manage.py schemamigration blog --auto
? The field 'User.test' does not have a default specified, yet is NOT NULL.
? Since you are adding 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:
也就是 需要增加一個欄位 test,原來的資料表有一條記錄是沒有這個欄位的,並且這個欄位還不能是空。一旦添加了欄位,原來的記錄要想保持正確,就必須要手動指定。有兩個選項,第一個放棄操作,新增一個預設的欄位在 models。第二個選項是 手動指定一個欄位 (columns)。這裡我們選擇 2,會顯示如下
(pythonenv)[email protected]:~/project/python/vitrual/dblog$ python manage.py schemamigration blog --auto
? The field 'User.test' does not have a default specified, yet is NOT NULL.
? Since you are adding 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: 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()
>>>
此時只要給已經存在的記錄手動指定欄位的值就行 輸入 'test' 如一下
(pythonenv)[email protected]:~/project/python/vitrual/dblog$ python manage.py schemamigration blog --auto
? The field 'User.test' does not have a default specified, yet is NOT NULL.
? Since you are adding 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: 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()
>>> 'test'
+ Added field test on blog.User
Created 0008_auto__add_field_user_test.py. You can now apply this migration with: ./manage.py migrate blog
此時 ,再執行
python manage.py migrate app_name
得到下面的提示
(pythonenv)[email protected]:~/project/python/vitrual/dblog$ python manage.py migrate blog
Running migrations for blog:
- Migrating forwards to 0008_auto__add_field_user_test.
> blog:0008_auto__add_field_user_test
- Loading initial data for blog.
No fixtures found.
此時,我們的資料表就添加了一個 test 欄位。資料庫的欄位變成 usname= rsj217 password=111 [email protected] test='test'
刪除一個欄位
有增加就有刪除。現在我們刪除 剛才那個 test 欄位
修改 models
class User(models.Model):
username = models.CharField(max_length=20, unique=True)
password = models.CharField(max_length=40)
email = models.EmailField(max_length=80, unique=True)
更改之後執行
python manage.py schemamigration app_name --auto
操作和效果如下
(pythonenv)[email protected]:~/project/python/vitrual/dblog$ python manage.py schemamigration blog --auto
? The field 'User.test' does not have a default specified, yet is NOT NULL.
? Since you are 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
? 3. Disable the backwards migration by raising an exception.
? 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()
>>> 'test'
- Deleted field test on blog.User
Created 0009_auto__del_field_user_test.py. You can now apply this migration with: ./manage.py migrate blog
(pythonenv)[email protected]:~/project/python/vitrual/dblog$ python manage.py migrate blog
Running migrations for blog:
- Migrating forwards to 0009_auto__del_field_user_test.
> blog:0009_auto__del_field_user_test
- Loading initial data for blog.
No fixtures found.
(pythonenv)[email protected]:~/project/python/vitrual/dblog$
這樣就刪除了剛才那個 test 欄位
修改欄位屬性
第三個操作是最懵懂,搞了很久才成功。例如 修改 models 的 username 屬性 刪除 unique = True,修改models 如下
class User(models.Model):
username = models.CharField(max_length=20)
password = models.CharField(max_length=40)
email = models.EmailField(max_length=80, unique=True)
更改之後執行
python manage.py schemamigration app_name --auto
顯示
(pythonenv)[email protected]:~/project/python/vitrual/dblog$ python manage.py schemamigration blog --auto
- Deleted unique constraint for ['username'] on blog.User
Created 0010_auto__del_unique_user_username.py. You can now apply this migration with: ./manage.py migrate blog
此時,如果直接 執行
python manage.py migrate app_name
一般情況下沒問題,直接更改。有時候會出現錯誤 "Database is locked" 。此時,只需要關閉 命令列,重新開啟就可以了。重新開啟 執行
python manage.py migrate app_name
通常,只要原資料庫存在記錄,更改資料庫結構之後,一定要保持現有的記錄也要適用更改後的結構,否則會報錯。
例如剛才把 欄位唯一刪除了,要是添加了兩個同名使用者名稱,再把欄位唯一增加回來,此時資料庫記錄就會存在兩條使用者名稱一樣的記錄,會報錯,只能更改為不同的。