Django遷移
學習目標:
- 如何在不編寫任何SQL語句的情況下創建數據庫表
- 更改model如何自動修改數據庫
- 如何還原對數據庫所做的更改
遷移能解決的問題
如果你不了解Django或者WEB開發,肯定是不熟悉數據庫遷移的概念的。
在學習它之前,首先我們需要明確它是干什么的,Django使用它旨在與關系型數據庫結合使用,將數據存儲在PostgreSQL
,Mysql
或者SQLite
等關系型數據庫管理系統中.
在關系數據庫中,數據以表格形式組織。數據庫表具有一定數量的列,但它可以包含任意數量的行。每列都有一個特定的數據類型,如某個特定最大長度的字符串或正整數。所有表及其列及其各自數據類型的描述稱為數據庫模式。
Django支持的所有數據庫系統都使用語言SQL來創建,讀取,更新和刪除關系數據庫中的數據。SQL還用於創建,更改和刪除數據庫表本身。
直接使用SQL可能非常麻煩,因此為了讓我們的開發工作更加輕松,Django附帶了一個對象關系映射器,簡稱ORM。ORM將關系數據庫映射到面向對象編程的世界。可以在Python中編寫Django模型,而不是在SQL中定義數據庫表。模型定義數據庫字段,這些字段對應於其數據庫表中的列。
以下是Django模型類如何映射到數據庫表的示例:
但是只是在Python文件中定義一個模型類並不會使數據庫表格無處不在。創建數據庫表來存儲Django模型是數據庫遷移的工作。此外,無論何時對模型進行更改(如添加字段),都必須更改數據庫。遷移也處理這個問題。
以下是Django遷移讓我們的開發工作更加輕松的幾種方式:
1、不使用SQL對數據庫進行修改
在Django中,如果沒有遷移,就必須在使用的時候鏈接到數據庫並且輸入一堆SQL命令,或者使用一些圖形工具在每次要更改模型定義時修改數據庫模式。
在Django中,遷移主要是用Python代碼完成的,因此除非你有非常高級的需求用法,否則你不需要操作任何SQL。
2、避免重復
如果創建模型后,編寫sql語句創建數據庫表,則會造成重復現象。
但是從模型中生成遷移,就能確保不會重復
3、確保模型定義和數據模式同步
通常,我們會有多個數據庫實例,例如,團隊中每個開發人員的一個數據庫,用於測試的數據庫和包含實時數據的數據庫。
如果沒有遷移,則必須對每個數據庫執行任何模式更改,並且必須跟蹤已對哪個數據庫進行了哪些更改。
使用Django Migrations,就可以輕松地使多個數據庫與模型保持同步。
4、跟蹤版本控制(git)中的數據庫模式更改
像Git這樣的版本控制系統非常適合代碼,但對數據庫模式來說並不是那么多。
由於遷移在Django中是普通的Python,因此您可以將它們放在版本控制系統中,就像任何其他代碼一樣。
創建遷移
在遷移之前首先得創建一個Django項目,具體怎么創建就不做過多贅述啦。直接開始吧
在做遷移之前,我們首先要創建模型。在app01/models.py
中添加此類
class User(models.Model):
name = models.CharField(max_length=32)
password = models.CharField(max_length=64)
一個最簡單的用戶模型類。
模型創建完成之后的第一件事就是為他創建遷移。
> python manage.py makemigrations
# 有的同學執行了以上命令后會發現不行,報錯了
"""
File "manage.py", line 16
) from exc
^
SyntaxError: invalid syntax
"""
這就很難受了,為什么呢,因為隨着時間的增長,Django的版本已經更新到2.3以后了,而在Django1.7以后,執行以上代碼都會報這個錯誤。我們需要將python替換成python3
> python3 manage.py makemigrations
"""
Migrations for 'hello_world':
hello_world/migrations/0001_initial.py
- Create model User
"""
這就成功了!!!
執行成功后,在migrations目錄現在包含一個新文件:0001_initial.py
"""
當我們運行完 makemigrations 命令,如果你沒有配置數據庫,它還會自動創建db.sqlite3數據庫.這個是Django默認的配置,同時也是SQLite獨有的配置。如果是其他數據庫的話,例如:Mysql、PostgreSQL等,就必須在運行之前自己創建數據庫了
"""
遷移成功后,我們接着來查看你的數據庫,會發現它雖然被創建出來了,但是他依然是空的。
> python3 manage.py dbshell
SQLite version 3.24.0 2018-06-04 14:10:15
Enter ".help" for usage hints.
sqlite> .tables
sqlite>
應用遷移
雖然現在我們已經創建了遷移工作,但是要想要實際在數據庫中進行任何修改,就必須執行migrate
命令:
> python3 manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, hello_world, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying hello_world.0001_initial... OK
Applying sessions.0001_initial... OK
執行完這條命令,會發現有很多輸出,根據輸出來看,我們的遷移已經成功應用,那么這些遷移中還有一些我們不知道的東西,它們來自於哪里呢?
還記得配置文件中的INSTALLED_APPS
嗎?其中列出的其他一些應用程序也帶有遷移功能,migrate
管理命令默認情況下會為所有已安裝的應用程序應用遷移。
再來看一下數據庫:
SQLite version 3.24.0 2018-06-04 14:10:15
Enter ".help" for usage hints.
sqlite> .tables
auth_group django_admin_log
auth_group_permissions django_content_type
auth_permission django_migrations
auth_user django_session
auth_user_groups hello_world_user
auth_user_user_permissions
sqlite>
現在我們的數據庫已經出現了多個表,我們可以從他們的名字上來了解他們的作用。
# 可以通過.schema命令查看已經生成的表
sqlite> .schema --indent hello_world_user
CREATE TABLE IF NOT EXISTS "hello_world_user"(
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" varchar(32) NOT NULL,
"password" varchar(64) NOT NULL
);
"""
.schema命令打印出CREATE將執行以創建表的語句。該參數--indent將sql語句格式化。即使不熟悉SQL語法,也可以看到hello_world_user表的模式反映了user模型的字段。
"""
如果你再次進行遷移的話,會發現不會將所有的模型表重新執行一遍,因為Django會記住已經應用了那些遷移,不會對已經遷移過的,在重新運行。
模型修改
你的model文件一定不是一成不變的,隨着你項目的完善,功能的添加,你的模型肯定會發生變化,可以添加、刪除字段或者更改類型還有選項。
在更改模型類的時候,肯定還需要更改用於存儲這些模型的數據庫表。如果模型定義與當前數據模式不匹配,很可能就會報錯:django.db.utils.OperationalError
具體更改方法:
依次執行:
> python3 manage.py makemigrations
> python3 manage.py migrate
列出遷移
如果想要知道項目中存在那些遷移,可以直接通過以下命令查看
python3 manage.py showmigrations
取消應用遷移
創建以及應用遷移都已經搞定了,知道如如何通過它們去更改數據庫模式,但是有些時候我們可能需要執行一些撤銷操作以切換回早期的數據庫模式,比如:
- 測試公司項目的中寫的遷移
- 遷移之后出現bug
- 同時處理不同數據庫修改的多個功能
- 想要還原在數據庫中具老架構的備份
所以這個時候就需要取消遷移來幫助我們了。
> python3 manage.py migrate hello_world 0001_initial
執行它就可以將遷移取消應用,也意味着對數據庫的更改也被取消了
取消應用遷移不會刪除其遷移文件。下次運行該migrate
命令時,將再次應用遷移。
"""
不要將未應用的遷移與您最常用的文本編輯器中的撤消操作混淆。
並非所有數據庫操作都可以完全還原。如果從模型中刪除字段,創建遷移並應用它,Django將從數據庫中刪除相應的列。
取消應用遷移將重新創建列,但它不會帶回存儲在該列中的數據!
"""
總結
Django遷移的基本步驟:
- 創建或更新模型類
- 執行
python3 manage.py makemigrations <app name(可不寫)>
- 執行
python3 manage.py migrate
遷移所有內容或python3 manage.py migrate <app name>
遷移單個app - 根據需求重復操作
這個工作流程在大多數情況下都可以搞定,但如果事情沒有按預期進行,還可以列出或者取消應用遷移幫助我們操作。