您好,登錄后才能下訂單哦!
使用django怎么實現多數據庫?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
定義及路由機制
定義
在settings里面的DATABASES是一個字典,用于定義需要的數據庫,如下,一共定義了兩個數據庫。
DATABASES = { 'default': { 'NAME': 'app_data', 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'USER': 'postgres_user', 'PASSWORD': 's3krit' }, 'user1': { 'NAME': 'user1_data', 'ENGINE': 'django.db.backends.mysql', 'USER': 'mysql_user', 'PASSWORD': 'priv4te' } 'user2': { 'NAME': 'user2_data', 'ENGINE': 'django.db.backends.mysql', 'USER': 'mysql_user', 'PASSWORD': 'priv4te' } }
那么什么時候調用default什么時候調用users數據庫呢,這就需要下面的路由。
路由注冊
class User1Router(object): """ A router to control all database operations on models in the auth application. """ def db_for_read(self, model, **hints): """ Attempts to read auth models go to auth_db. """ if model._meta.app_label == 'auth': return 'user1' return None def db_for_write(self, model, **hints): """ Attempts to write auth models go to auth_db. """ if model._meta.app_label == 'auth': return 'user1' return None def allow_relation(self, obj1, obj2, **hints): """ Allow relations if a model in the auth app is involved. """ if obj1._meta.app_label == 'auth' or \ obj2._meta.app_label == 'auth': return True return None def allow_syncdb(self, db, model): """ Make sure the auth app only appears in the 'auth_db' database. """ if db == 'auth_db': return model._meta.app_label == 'auth' elif model._meta.app_label == 'user1': return False return None class User2Router(object): """ A router to control all database operations on models in the auth application. """ def db_for_read(self, model, **hints): """ Attempts to read auth models go to auth_db. """ if model._meta.app_label == 'auth3': return 'user2' return None def db_for_write(self, model, **hints): """ Attempts to write auth models go to auth_db. """ if model._meta.app_label == 'auth3': return 'user2' return None def allow_relation(self, obj1, obj2, **hints): """ Allow relations if a model in the auth app is involved. """ if obj1._meta.app_label == 'auth' or \ obj2._meta.app_label == 'auth': return True return None def allow_syncdb(self, db, model): """ Make sure the auth app only appears in the 'auth_db' database. """ if db == 'auth_db': return model._meta.app_label == 'auth3' elif model._meta.app_label == 'user2': return False return None
User1Router的路由邏輯是,如果model所屬的app是auth的話,就使用user1數據庫,否則就使用其他的;User2Router的邏輯類似。
如何注冊路由
光定義路由程序無法調用到,還需要注冊到django中,在settings中定義
DATABASE_ROUTERS = ['path.to.User1Router' , 'path.to.User2Router']
path.to:是User1Router的完整python包路徑,所以,User1Router不一定要在settings中實現,可以在任何地方。
路由機制
那么django是如何選擇其中一個路由的呢?
1. django按照注冊的順序輪詢DATABASE_ROUTERS,所以首先驗證User1Router是否返回了非空字符串,如果是,則使用User1Router;如果不是則接著驗證后面的Router;
2. 同樣驗證User2Router,如果User2Router返回了非空字符串,則使用User2Router;如果不是則使用default數據庫;
3. 所以可以看出,路由注冊的順序是會影響最后的結果的,注冊在前面的路由會優先被使用;
自動路由和手動路由
上面定義的Router是自動路由,意思是django會自動輪詢所注冊的路由器,某個model會保存在哪個數據庫,是django通過注冊的Router自動獲得的,在編碼中你不需要指定;
手動路由,則是你可以在編碼中指定某個model要保存到哪個數據庫。
而且手動路由也有性能方面的優點,如果定義了很多個數據庫,每次保存或者讀取model都要把輪詢一遍路由列表,顯然效率有些低,如果程序邏輯清楚的知道當前的代碼應該連接哪個數據庫,顯示指定的方式顯然效率更高。
手動路由
查詢
使用using函數,參數就是要查詢的數據庫
User.objects.using('user1').all()
保存或者更新
使用save的using參數,值就是要使用的數據庫
>>> my_object.save(using='user1')
刪除
使用delete的using參數
>>> user_obj.delete(using='user1')
分庫技術
下面緊緊介紹分庫的思路。
垂直分庫
即一個app對應一個數據庫,上面自動路由的例子就是一個垂直分庫的例子,auth2使用user1數據庫,auth3使用user2數據庫。當然也可以使用手動路由。
水平分庫
水平分庫建議使用手動路由,因為每個model的分庫機制可能都不一樣,自動路由實現起來有些麻煩會造成性能不高,而手動路由,每個model根據自己的規則來獲得不同的數據庫。
補充知識:Django實現數據庫讀寫分離、一主多從、分庫
讀寫分離
在工程中,通常需要實現mysql讀寫分離。在Django中需要支持讀寫分離的話,只需要很簡單的幾步就可以了。
首先,配置讀庫和寫庫。
在django項目的settings.py中,配置讀庫和寫庫。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'WIPS', 'USER': 'mysql', 'PASSWORD': '360tianxun#^)Sec', 'HOST': '', 'PORT': '', }, 'slave': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'TEST', 'USER': 'mysql', 'PASSWORD': '360tianxun#^)Sec', 'HOST': '', 'PORT': '', }, }
接下來,需要創建數據庫的路由分發類。
可以在appname/utils下創建一個db_router.py文件,在文件中定義db_router類。類中實現讀庫寫庫的選擇。
class DBRouter(object): def db_for_read(self, model, **hints): return "slave" def db_for_write(self, model, **hints): return "default" def allow_relation(self, obj1, obj2, **hints): return True
最后,在settings.py中添加路由配置。
DATABASE_ROUTERS = ['appname.utils.db_router.DBRouter' ]
重新啟動Django就完成了。
這里需要注意的是,Django只完成了讀寫分離,但mysql主庫、從庫的同步操作并不歸django負責,依然需要mysql實現。
一主多從
一主多從的方案在實際應用中是更常見的配置。在上面配置的基礎上,只需要修改幾個地方,就可以實現一主多從了。
首先,修改settings.py,增加全部從庫的設置。
其次,修改db_router類中db_for_read(),下面是隨機選取讀庫的例子。也可以根據實際的需要,選取不同的調度算法。
class DBRouter(object): def db_for_read(self, model, **hints): import random return random.choice(['slave', 'slave2', 'slave3'])
分庫
當需要不同的app使用不同的庫時,可以利用model中的app_label來實現db的路由。
class DBRouter(object): def db_for_read(self, model, **hints): if model._meta.app_label == 'app01': import random return random.choice(['app01_slave1', 'app01_slave2', 'app01_slave3']) if model._meta.app_label == 'app02': return "app02_slave"
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。