Django——多个数据库
Django——多個數據庫
官方文檔:https://docs.djangoproject.com/en/3.2/topics/db/multi-db/
主要介紹Django 對與多個數據庫交互的支持。
1. 數據庫服務器 DATABASES
在Django中使用多個數據庫的第一步是告訴Django將要使用的數據庫服務器。 這是通過使用 DATABASES 設置完成的。 這個設置將數據庫別名映射到特定連接的設置字典中,別名是在Django中引用特定數據庫的一種方式。 內部字典中的設置在DATABASES文檔中有完整的描述。
數據庫可以有您選擇的任何別名。 但是,別名默認值有特殊的意義。 當沒有選擇其他數據庫時,Django會使用default 別名的數據庫。
下面是 settings.py 代碼片段的一個例子,它定義了兩個數據庫——一個默認的 PostgreSQL 數據庫和一個名為users的 MySQL 數據庫:
DATABASES = {'default': {'NAME': 'app_data','ENGINE': 'django.db.backends.postgresql','USER': 'postgres_user','PASSWORD': 's3krit'},'users': {'NAME': 'user_data','ENGINE': 'django.db.backends.mysql','USER': 'mysql_user','PASSWORD': 'priv4te'} }如果默認數據庫的概念在項目的上下文中沒有意義,那么您需要始終謹慎地指定要使用的數據庫。 Django要求定義一個默認的數據庫條目,但是如果不使用的話,參數字典可以保留為空。 要做到這一點,你必須為所有應用程序的模型設置 DATABASE_ROUTERS,包括你正在使用的任何應用程序和第三方應用程序的模型,這樣查詢就不會路由到默認數據庫。
下面是 settings.py 代碼段的一個示例,它定義了兩個非默認數據庫,默認條目故意為空:
DATABASES = {'default': {},'users': {'NAME': 'user_data','ENGINE': 'django.db.backends.mysql','USER': 'mysql_user','PASSWORD': 'superS3cret'},'customers': {'NAME': 'customer_data','ENGINE': 'django.db.backends.mysql','USER': 'mysql_cust','PASSWORD': 'veryPriv@ate'} }如果你試圖訪問一個沒有在 database 設置中定義的數據庫,Django會拋出 Django.utils.connection. connectiondoesnotexist 異常。
2. 同步數據庫
遷移管理命令一次操作一個數據庫。
(default是默認的數據庫,在這里可以為{},但是一旦為空不可以執行 python manage.py migrate)
默認情況下,它在默認數據庫上操作,但是通過提供 ——database 選項,可以告訴它同步一個不同的數據庫。 因此,要將上面第一個例子中的所有模型同步到所有數據庫,
您需要調用:
python manage.py makemigrations # 生成遷移文件 python manage.py migrate --database=users如果您不希望將每個應用程序同步到特定的數據庫,那么可以定義一個數據庫路由器,該路由器實現一個限制特定模型可用性的策略。
如果與上面的第二個示例一樣,您將默認數據庫保留為空,則必須在每次運行 migrate 時提供一個數據庫名稱(分多次遷移數據)。 省略數據庫名稱將引發錯誤。
對于第二個例子:
python manage.py migrate --database=users python manage.py migrate --database=customers3. 自動數據庫路由(默認路由方案)
使用多個數據庫的最簡單方法是建立一個數據庫路由方案。
默認的路由方案確保對象保持“粘性”到他們的原始數據庫(即,從 xxx 數據庫檢索的對象將保存在同一個數據庫)。 默認路由方案確保如果沒有指定數據庫,所有查詢都返回到默認數據庫。
你不需要做任何事情來激活默認路由方案——它是在每個Django項目中“開箱即用”提供的。
但是,如果您想實現更強大的數據庫分配行為,您可以定義自己的數據庫路由器。
4. 自定義路由方案(數據庫路由器)
一個 database Router 是一個提供了四個方法的類:
- db_for_read(model, **hints) - 應用于讀取類型對象的數據庫模型,如果數據庫提供附加信息會在hints字典中提供,最后如果沒有則返回None
 
- db_for_write(model, **hints) - 應用于寫入類型對象的數據庫模型,hints字典提供附加信息,如果沒有則返回None
 
- allow_relation(obj1, obj2, **hints) - 外鍵操作,判斷兩個對象之間是否是應該允許關系,是返回True,否則返回False,如果路由允許返回None
 
- allow_migrate(db, app_label, model_name=None, **hints) - db確定是否允許在具有別名的數據庫上運行遷移操作,操作運行返回True,否則返回False,或者返回None,如果路由器沒有意見。
- app_label:位置參數是正在遷移的應用程序的標簽。
- model_name:多個遷移操作設置模型的值,如:model._meta.app_label
 
路由器不必提供所有這些方法——它可以省略一個或多個。 如果其中一個方法被省略,Django將在執行相關檢查時跳過該路由器。
4.1 使用路由器
使用 DATABASE_ROUTERS 設置安裝數據庫路由器。
這個設置定義了一個類名列表,每個類名指定一個主路由器(django.db.router)使用的路由器。
主路由器用于Django的數據庫操作來分配數據庫的使用。 每當查詢需要知道使用哪個數據庫時,它就調用主路由器,提供一個模型和一個提示(如果可用的話)。 然后Django依次嘗試每個路由器,直到找到數據庫建議。 如果找不到提示,則嘗試提示實例的當前 instance._state.db。 如果沒有提供提示實例,或者 instance._state.db 為None,主路由器將分配默認數據庫。
4.2 案例
4.2.1 創建數據庫路由
在 settings.py 同級目錄下創建 數據庫路由器( db_router.py ),app應用會根據指定的路由選擇數據庫:
from .settings import DATABASE_APPS_MAPPINGDATABASE_MAPPING = DATABASE_APPS_MAPPING# 數據庫路由分發 class database_router(object):def db_for_read(self, model, **hints):""""Point all read operations to the specific database.""""""將所有讀操作指向特定的數據庫。"""if model._meta.app_label in DATABASE_MAPPING:return DATABASE_MAPPING[model._meta.app_label]return Nonedef db_for_write(self, model, **hints):"""Point all write operations to the specific database.""""""將所有寫操作指向特定的數據庫。"""if model._meta.app_label in DATABASE_MAPPING:return DATABASE_MAPPING[model._meta.app_label]return Nonedef allow_relation(self, obj1, obj2, **hints):"""Allow any relation between apps that use the same database.""""""允許使用相同數據庫的應用程序之間的任何關系"""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 Trueelse:return Falseelse:return Nonedef allow_syncdb(self, db, model):"""Make sure that apps only appear in the related database.""""""確保這些應用程序只出現在相關的數據庫中。"""if db in DATABASE_MAPPING.values():return DATABASE_MAPPING.get(model._meta.app_label) == dbelif model._meta.app_label in DATABASE_MAPPING:return Falsereturn Nonedef allow_migrate(self, db, app_label, model=None, **hints):"""Make sure the auth app only appears in the 'auth_db' database.""""""確保身份驗證應用程序只出現在“authdb”數據庫中。"""if db in DATABASE_MAPPING.values():return DATABASE_MAPPING.get(app_label) == dbelif app_label in DATABASE_MAPPING:return Falsereturn None4.2.2 settings.py 配置
在 setting.py 中配置 DATABASE_ROUTERS 指定自由路由文件:
# 數據庫設置, xxxx0001為項目名稱 DATABASE_ROUTERS = ['xxxx0001.db_router.database_router']在 setting.py 中 DATABASE_ROUTERS 下面設置app與數據庫匹配路由表,采用字典方式app名對應數據庫映射名:
DATABASE_APPS_MAPPING = {'app01':'default','app02':'db2', }4.2.3 生成表并同步數據
分別在app01和app02下創建model類,用于生成數據表:
此處只定義了 app02 的模型,注意:加上app_label以后就會指明所屬的app
from django.db import modelsclass IntelligentTableView(models.Model):table_name = models.CharField(max_length=255, verbose_name='報表名稱')center = models.CharField(max_length=50, verbose_name='所屬中心')on_line = models.CharField(max_length=50, verbose_name='所屬線條')remake = models.CharField(max_length=255, verbose_name='備注')create_name = models.CharField(max_length=50, verbose_name='創建人')create_date = models.DateTimeField(auto_now=True, verbose_name='創建時間')is_del = models.BooleanField(default=False, verbose_name='是否刪除')class Meta:db_table = 'intelligent_table' # 表名verbose_name = '智能報表'app_label = 'app02' # 指明app名稱,用來對應app 和 數據庫的map表migrate管理命令一次只能操作一個數據庫,默認操作default數據庫,使用–database指定同步的數據庫:
python manage.py migrate # 生成表數據同步 python manage.py makemigrations # # 生成遷移文件 python manage.py migrate --database=default # 同步指定數據庫 python manage.py migrate --database=db2總結
以上是生活随笔為你收集整理的Django——多个数据库的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        