一、說明:
在開發(fā) Django 項目的時候,很多時候都是使用一個數(shù)據(jù)庫,即 settings 中只有 default 數(shù)據(jù)庫,但是有一些項目確實也需要使用多個數(shù)據(jù)庫,這樣的項目,在數(shù)據(jù)庫配置和使用的時候,就比較麻煩一點。
二、Django使用多個數(shù)據(jù)庫中settings中的DATABASES的設(shè)置
2.1 默認(rèn)只是用一個數(shù)據(jù)庫時 DATABASES 的設(shè)置(以 SQLite 為例)
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'db.sqlite3', } }
2.2 Django 數(shù)據(jù)庫支持的?ENGINE 類型
-
'django.db.backends.postgresql'
'django.db.backends.mysql'
'django.db.backends.sqlite3'
'django.db.backends.oracle'
2.3 設(shè)置了多個數(shù)據(jù)庫后 settings 中的 DATABASES 的設(shè)置
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' } }
三、實現(xiàn)思路
- 多個應(yīng)用對應(yīng)多個數(shù)據(jù)庫和一個應(yīng)用對應(yīng)多個數(shù)據(jù)庫
- 情況一:項目有多個 應(yīng)用app 且需要使用到多個數(shù)據(jù)庫
- 情況二:項目只有一個應(yīng)用app, 且但需要使用到多個數(shù)據(jù)庫,
- 這兩種情況的實現(xiàn)思路其實都是一樣的,都是為每個數(shù)據(jù)庫創(chuàng)建一個應(yīng)用,即這個應(yīng)用只對接一個數(shù)據(jù)庫,如果這個應(yīng)用不需要寫任何業(yè)務(wù)邏輯的代碼,也需要創(chuàng)建一個空的應(yīng)用,主要是用來做數(shù)據(jù)庫遷移的
- 核心思想就是:一個model類對應(yīng)一個數(shù)據(jù)庫,通過數(shù)據(jù)庫路由和model定義時指定的all_label來實現(xiàn)。
四、案例實現(xiàn)
第一步:創(chuàng)建需要的 應(yīng)用app,并且在?INSTALLED_APPS 中引用
其中db1_app這個應(yīng)用主要是用來對接數(shù)據(jù)庫db1的
其中db2_app這個應(yīng)用主要是用來對接數(shù)據(jù)庫db2的
其中test_app這個應(yīng)用主要用來實現(xiàn)業(yè)務(wù)邏輯的
? ? ? ? ? ? ? ? ?
第二步:創(chuàng)建 應(yīng)用app 和 數(shù)據(jù)庫之間的映射關(guān)系
在settings.py 文件夾中設(shè)置?DATABASE_APPS_MAPPING?的字典,里面主要是配置 應(yīng)用app 和數(shù)據(jù)庫的對應(yīng)關(guān)系
DATABASE_APPS_MAPPING = { "db1_app": "db1", # db1_app 對應(yīng) db1 數(shù)據(jù)庫 "db2_app": "db2" # db2_app 對應(yīng) db2 數(shù)據(jù)庫 }
第三步:創(chuàng)建數(shù)據(jù)庫路由
在項目的主文件夾即 settings.py 的同目錄下創(chuàng)建一個?database_router.py 文件,該文件的作用就是給不同應(yīng)用app 配置不同的數(shù)據(jù)庫。
# _*_ 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): # 設(shè)置 應(yīng)用app 讀取時數(shù)據(jù)庫的設(shè)置 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. 根據(jù)app_label的值只在相應(yīng)的數(shù)據(jù)庫中創(chuàng)建一個表,如果刪除該def或 不指定過濾條件,則一個Model會在每個數(shù)據(jù)庫里都創(chuàng)建一個表。 """ 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為路由中創(chuàng)建的類名 DATABASE_ROUTERS = ['django_db_demo.database_router.DatabaseAppsRouter']
第五步:創(chuàng)建model類
說明:model 可以根據(jù)需要卸載任何一個應(yīng)用app的model.py文件中,也可以分散寫在多個應(yīng)用的model.py中,這個根據(jù)自己的需要即可,但是如何推薦一定要在model類的Meta中指定app_label。不然會全部將表創(chuàng)建到default數(shù)據(jù)庫中
from django.db import models class SqliteModel(models.Model): """帳號和用戶關(guān)聯(lián)""" sqlite_name = models.CharField(max_length=20) class Meta: # 當(dāng)前這個 SqliteModel 定義的數(shù)據(jù)庫的表將會創(chuàng)建在test_app 對應(yīng)的default 數(shù)據(jù)庫中 app_label = "test_app" # 當(dāng)有多個數(shù)據(jù)庫鏈接的時候,要通過app_label 來區(qū)分這個model對應(yīng)那個數(shù)據(jù)庫 class Db1Model(models.Model): """帳號和用戶關(guān)聯(lián)""" db1_name = models.CharField(max_length=20) class Meta: # 當(dāng)前這個Db1Model 定義的數(shù)據(jù)庫的表將會創(chuàng)建在 db1_app 對應(yīng)的 db1 數(shù)據(jù)庫中 app_label = "db1_app" # 當(dāng)有多個數(shù)據(jù)庫鏈接的時候,要通過app_label 來區(qū)分這個model對應(yīng)那個數(shù)據(jù)庫 class Db2Model(models.Model): """帳號和用戶關(guān)聯(lián)""" db2_name = models.CharField(max_length=20) class Meta: # 當(dāng)前這個Db2Model 定義的數(shù)據(jù)庫的表將會創(chuàng)建在 db2_app 對應(yīng)的 db1 數(shù)據(jù)庫中 app_label = "db2_app" # 當(dāng)有多個數(shù)據(jù)庫鏈接的時候,要通過app_label 來區(qū)分這個model對應(yīng)那個數(shù)據(jù)庫
第六步:數(shù)據(jù)遷移
python3 manage.py makemigrations python3 manage.py migrate --database=default # 當(dāng)有多個數(shù)據(jù)庫,需要遷移多次 python3 manage.py migrate --database=db1 python3 manage.py migrate --database=db2
第七步:查看遷移:
model對應(yīng)的表,分別遷移到不同的數(shù)據(jù)庫成功,剩下的增刪改查的就正常引入model對象即可,這樣就實現(xiàn)了,不同的model對象,對應(yīng)不用數(shù)據(jù)庫的表。文章來源:http://www.zghlxwxcb.cn/news/detail-420224.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-420224.html
第五步:總結(jié)
- 創(chuàng)建多個數(shù)據(jù)庫連接設(shè)置
- 創(chuàng)建多個數(shù)據(jù)與應(yīng)用app的映射關(guān)系
- 創(chuàng)建數(shù)據(jù)庫路由
- 創(chuàng)建model類的時候置指明app_label,即這個model是屬于那個app,從而覺得遷移到那個數(shù)據(jù)庫
到了這里,關(guān)于django使用多個數(shù)據(jù)庫實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!