本文首發於公眾號:Hunter後端
這一篇筆記介紹一下 Django 裡使用多資料庫操作。
在第二十二篇筆記中只介紹了多資料庫的定義、同步命令和使用方式,這一篇筆記作為補充詳細介紹如何對 Django 系統的多個資料庫進行鍼對的建表同步操作。
以下是本篇筆記目錄:
這裡還是複用之前的 Django 系統,這裡我們額外建立兩個資料庫連線,之前的 default 還是不變:
# hunter/settings.py
DATABASES = {
'default': {
...
},
'user': {
'ENGINE': "django.db.backends.mysql",
'NAME': "db_1",
"USER": "root",
"PASSWORD": "123456",
"HOST": "192.168.1.10",
"PORT": 3306,
},
'other': {
'ENGINE': "django.db.backends.mysql",
'NAME': "db_2",
"USER": "root",
"PASSWORD": "123456",
"HOST": "192.168.1.11",
"PORT": 3306,
},
}
資料庫裡的連線名稱分別是 user 和 other。
注意,這裡我們使用的是不同的資料庫 DATABASE,分別是 db_1 和 db_2,他們可以在一個地址的 MySQL 裡,也可以在不同地址。
接下來我們以 application 為整體來指定 model 對資料庫進行操作。
上面這句話這裡釋義一下,就是說針對多個資料庫,我們這裡預設使用整個 application 下的 model 表與之對應,比如說 new_user 這個 app 下的 model 的 migration 操作都寫入 DATABASE 下 user 對應的資料庫。
當然,這個操作過程我們還需要在 settings.py 中定義一個對映 DATABASE_APPS_MAPPING,這個我們後面再說。
首先,我們分別建立兩個 application,一個 application 名為 new_user,另一個名為 other_info,使用下面的命令建立:
python3 manage.py startapp new_user
python3 manage.py startapp other_info
然後在系統的根目錄會出現這兩個資料夾。
然後在 settings.py 中註冊這兩個 app:
# hunter/settings.py
INSTALLED_APPS = [
...
'new_user.apps.NewUserConfig',
'other_info.apps.OtherInfoConfig',
...
]
然後設定 application 與 DATABASE 的對應關係:
DATABASE_APPS_MAPPING = {
"new_user": "user",
"other_info": "other",
}
在這裡的這個對映關係的 key 是我們的 application 的名稱,value 則是 settings.py 中 DATABASES 對應的資料庫的 key。
比如這裡我們將 new_user 這個 app 指定到了 user 資料庫。
接下來我們分別在兩個 application 下建立對應的 model:
# new_user/models.py
from django.db import models
class NewUser(models.Model):
pass
class Meta:
app_label = "new_user"
# other_info/models.py
from django.db import models
class OtherInfo(models.Model):
pass
class Meta:
app_label = "other_info"
在這兩個 model 裡,我手動給其新增了 app_label 欄位,值為各自所在 application 下的名,表示這個 model 是從屬於 app_label 這個 application 下。
其實對於每個 model,meta 資訊下都會有這個欄位,預設值為該 model 所處的 application 的名稱,這裡為了顯示對比,我額外標記了出來。
檢視 app_label 的方式為:
from new_user.models import NewUser
NewUser._meta.app_label
# new_user
而在前面的 settings.py 裡我們設定了 DATABASE_APPS_MAPPING 對映
DATABASE_APPS_MAPPING = {
"new_user": "user",
"other_info": "other",
}
所以這裡的 NewUser model 使用的就是 user 這個資料庫。
接下來我們可以進行 migration 操作來測試將表結構寫入 user 資料庫。
接下來我們建立 migration 檔案:
python3 manage.py makemigrations new_user
python3 manage.py makemigrations other_info
然後會在 new_user 和 other_info 下分別建立對應的 migration 檔案。
接下來進行 migrate 的時候需要指定 database 引數,也就是我們前面 settings.py 裡的 DATABASES 的對應的 key:
python3 manage.py migrate new_user --database=user
python3 manage.py migrate other_info --database=other
根據 settings.py 裡 DATABASE_APPS_MAPPING 裡的對映關係,--database 對應的引數就是相應的資料庫。
執行完上面的命令之後,在兩個對應的資料庫裡就會建立 django_migrations 表和 model 對應的表。
建立 django_migrations 表是因為每個 database 也需要記錄各自的 migration 遷移記錄。
至此,我們就將 application 下的 model 和 database 對應了起來。
前面我們將 model 和 database 對應了起來之後,在操作對應的 model 的時候還是需要 using() 來指定操作的 database:
from new_user.models import NewUser
NewUser.objects.using("user").create(id=1)
在這篇筆記裡,我們另外設定了兩個資料庫用於對應新建的 application,且在 DATABASE_APPS_MAPPING 中設定了 application 到 database 的對映,那麼沒有設定對映關係的 application 下的 model 其實就還是預設屬於 default 資料庫的。
比如我們之前建立的 blog 這個 application,就相當於是:
DATABASE_APPS_MAPPING = {
"blog": "default",
"new_user": "user",
"other_info": "other",
}
不過因為是預設設定,所以為了方便我們沒有顯式的設定出來。
並且,對於多個 application 是可以對應同一個資料庫連結的,比如我們預設的 default,沒有設定的 application 都對應的是 default 的資料庫連結。
假設我們又建立了一個名為 article 的 app,也想要對應 other 資料庫,可以這樣操作:
DATABASE_APPS_MAPPING = {
"blog": "default",
"new_user": "user",
"other_info": "other",
"article": "other",
}
這個操作是否可以呢?
可以,假設我們在 new_user 下建立一個 model,但是設定的是 other_info 的 app_label:
# new_user/models.py
class OtherInfoInNewUser(models.Model):
pass
class Meta:
app_label = "other_info"
然後我們對 new_user 這個 app 執行下面的操作是檢測不到有新 migration 的
python3 manage.py makemigrations new_user
因為當我們 makemigrations 指定 app 名稱的時候,系統會去檢測這個 app 下是否有屬於這個 app 的新的 model 變化,而我們設定 OtherInfoInNewUser 這個 model 卻從屬於 other_info,所以是檢測不到變化的。
只有當我們執行:
python3 manage.py makemigrations other_info
這個操作的時候,系統才會檢測到 app_label='other_info' 的 model 的變化,然後建立新的 migration。
上面這個操作雖然是可行的,但是為了統一管理,還是不推薦這麼操作。
如果想獲取更多後端相關文章,可掃碼關注閱讀: