Django筆記三十七之多資料庫操作(補充版)

2023-05-07 15:00:20

本文首發於公眾號:Hunter後端

原文連結:Django筆記三十七之多資料庫操作(補充版)

這一篇筆記介紹一下 Django 裡使用多資料庫操作。

在第二十二篇筆記中只介紹了多資料庫的定義、同步命令和使用方式,這一篇筆記作為補充詳細介紹如何對 Django 系統的多個資料庫進行鍼對的建表同步操作。

以下是本篇筆記目錄:

  1. DATABASES 定義
  2. application建立和設定
  3. migration 和 migrate 操作
  4. 幾個注意的點

1、DATABASES 定義

這裡還是複用之前的 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 裡,也可以在不同地址。

2、application建立和設定

接下來我們以 application 為整體來指定 model 對資料庫進行操作。

上面這句話這裡釋義一下,就是說針對多個資料庫,我們這裡預設使用整個 application 下的 model 表與之對應,比如說 new_user 這個 app 下的 model 的 migration 操作都寫入 DATABASE 下 user 對應的資料庫。

當然,這個操作過程我們還需要在 settings.py 中定義一個對映 DATABASE_APPS_MAPPING,這個我們後面再說。

建立application

首先,我們分別建立兩個 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與資料庫的對應設定

然後設定 application 與 DATABASE 的對應關係:

DATABASE_APPS_MAPPING = {
    "new_user": "user",
    "other_info": "other",
}

在這裡的這個對映關係的 key 是我們的 application 的名稱,value 則是 settings.py 中 DATABASES 對應的資料庫的 key。

比如這裡我們將 new_user 這個 app 指定到了 user 資料庫。

建立 model

接下來我們分別在兩個 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 資料庫。

3、migration 和 migrate 操作

接下來我們建立 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 對應了起來。

4、幾個注意的點

資料的增刪改查

前面我們將 model 和 database 對應了起來之後,在操作對應的 model 的時候還是需要 using() 來指定操作的 database:

from new_user.models import NewUser
NewUser.objects.using("user").create(id=1)

default資料庫

在這篇筆記裡,我們另外設定了兩個資料庫用於對應新建的 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",
}

某 app 下設定其他 app 的 model

這個操作是否可以呢?

可以,假設我們在 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。

上面這個操作雖然是可行的,但是為了統一管理,還是不推薦這麼操作。

如果想獲取更多後端相關文章,可掃碼關注閱讀: