django使用多個資料庫實現

Se7eN_HOU發表於2023-04-21

一、說明:

  在開發 Django 專案的時候,很多時候都是使用一個資料庫,即 settings 中只有 default 資料庫,但是有一些專案確實也需要使用多個資料庫,這樣的專案,在資料庫配置和使用的時候,就比較麻煩一點。

二、Django使用多個資料庫中settings中的DATABASES的設定

  2.1 預設只是用一個資料庫時 DATABASES 的設定(以 SQLite 為例)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',         
        'NAME': 'db.sqlite3',
    }
}

  2.2 Django 資料庫支援的 ENGINE 型別

    • 'django.db.backends.postgresql'
    • 'django.db.backends.mysql'
    • 'django.db.backends.sqlite3'
    • 'django.db.backends.oracle'

  2.3 設定了多個資料庫後 settings 中的 DATABASES 的設定

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db.sqlite3',
    },
    'db1': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mysql_test_db1',
        'USER': 'root',
        'PASSWORD': 'Se7eN521',
        'HOST': '127.0.0.1',
        'PORT': '3306'
    },
    'db2': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mysql_test_db2',
        'USER': 'root',
        'PASSWORD': 'Se7eN521',
        'HOST': '127.0.0.1',
        'PORT': '3306'
    }
}

三、實現思路

  1. 多個應用對應多個資料庫和一個應用對應多個資料庫
    1. 情況一:專案有多個 應用app 且需要使用到多個資料庫
    2. 情況二:專案只有一個應用app, 且但需要使用到多個資料庫,
  2. 這兩種情況的實現思路其實都是一樣的,都是為每個資料庫建立一個應用,即這個應用只對接一個資料庫,如果這個應用不需要寫任何業務邏輯的程式碼,也需要建立一個空的應用,主要是用來做資料庫遷移的
  3. 核心思想就是:一個model類對應一個資料庫,透過資料庫路由和model定義時指定的all_label來實現。

四、案例實現

  第一步:建立需要的 應用app,並且在 INSTALLED_APPS 中引用

    其中db1_app這個應用主要是用來對接資料庫db1的

    其中db2_app這個應用主要是用來對接資料庫db2的

    其中test_app這個應用主要用來實現業務邏輯的

                 django使用多個資料庫實現

 

  第二步:建立 應用app 和 資料庫之間的對映關係

    在settings.py 資料夾中設定 DATABASE_APPS_MAPPING 的字典,裡面主要是配置 應用app 和資料庫的對應關係

DATABASE_APPS_MAPPING = {
    "db1_app": "db1",   # db1_app 對應 db1 資料庫
    "db2_app": "db2"    # db2_app 對應 db2 資料庫
}

  第三步:建立資料庫路由

    在專案的主資料夾即 settings.py 的同目錄下建立一個 database_router.py 檔案,該檔案的作用就是給不同應用app 配置不同的資料庫。

# _*_ coding:utf-8 _*_
# @Time : 2023/4/20 5:37 下午

from django.conf import settings

DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING
print('DATABASE_MAPPING = {}'.format(DATABASE_MAPPING))

class DatabaseAppsRouter(object):

    # 設定 應用app 讀取時資料庫的設定
    def db_for_read(self, model, **hints)if model._meta.app_label in DATABASE_MAPPING:
            return DATABASE_MAPPING[model._meta.app_label]
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in DATABASE_MAPPING:
            return DATABASE_MAPPING[model._meta.app_label]
        return None

    def allow_relation(self, obj1, obj2, **hints):
        db_obj1 = DATABASE_MAPPING.get(obj1._meta.app_label)
        db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label)
        if db_obj1 and db_obj2:
            if db_obj1 == db_obj2:
                return True
            else:
                return False
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure that apps only appear in the related database.
        根據app_label的值只在相應的資料庫中建立一個表,如果刪除該def或
        不指定過濾條件,則一個Model會在每個資料庫裡都建立一個表。
        """
        if db in DATABASE_MAPPING.values():return DATABASE_MAPPING.get(app_label) == db
        elif app_label in DATABASE_MAPPING:
            return False
        return None

  第四步:在setting.py中配置 DATABASE_ROUTERS 指定自由路由檔案:

#test_django為專案名,database_router為路由檔名,DatabaseAppsRouter為路由中建立的類名
DATABASE_ROUTERS = ['django_db_demo.database_router.DatabaseAppsRouter']

  第五步:建立model類

    說明:model 可以根據需要解除安裝任何一個應用app的model.py檔案中,也可以分散寫在多個應用的model.py中,這個根據自己的需要即可,但是如何推薦一定要在model類的Meta中指定app_label。不然會全部將表建立到default資料庫中

from django.db import models

class SqliteModel(models.Model):
    """帳號和使用者關聯"""

    sqlite_name = models.CharField(max_length=20)
    class Meta:
        # 當前這個 SqliteModel 定義的資料庫的表將會建立在test_app 對應的default 資料庫中
        app_label = "test_app"      # 當有多個資料庫連結的時候,要透過app_label 來區分這個model對應那個資料庫
        db_table = "sqlite_test_table"   # 自定義的表名

class Db1Model(models.Model):
    """帳號和使用者關聯"""

    db1_name = models.CharField(max_length=20)
    class Meta:
        # 當前這個Db1Model 定義的資料庫的表將會建立在 db1_app 對應的 db1 資料庫中
        app_label = "db1_app"        # 當有多個資料庫連結的時候,要透過app_label 來區分這個model對應那個資料庫
        db_table = "db1_test_table"    # 自定義的表名

class Db2Model(models.Model):
    """帳號和使用者關聯"""

    db2_name = models.CharField(max_length=20)
    class Meta:
        # 當前這個Db2Model 定義的資料庫的表將會建立在 db2_app 對應的 db1 資料庫中
        app_label = "db2_app"       # 當有多個資料庫連結的時候,要透過app_label 來區分這個model對應那個資料庫
        db_table = "db2_test_table"   # 自定義的表名

  

  第六步:資料遷移

python3 manage.py makemigrations  
python3 manage.py migrate --database=default   # 當有多個資料庫,需要遷移多次
python3 manage.py migrate --database=db1
python3 manage.py migrate --database=db2 

  第七步:檢視遷移:

    model對應的表,分別遷移到不同的資料庫成功,剩下的增刪改查的就正常引入model物件即可,這樣就實現了,不同的model物件,對應不用資料庫的表。

    

 第五步:總結

  1. 建立多個資料庫連線設定
  2. 建立多個資料與應用app的對映關係
  3. 建立資料庫路由
  4. 建立model類的時候置指明app_label,即這個model是屬於那個app,從而覺得遷移到那個資料庫

相關文章