同一型號我有以下問題:不同的數據庫與Django的
我需要爲每個用戶相同型號不同的數據庫(或一組用戶)。我有辦法找出用戶與哪個數據庫相關。問題是我總是必須在每個查詢中使用using
方法。
例如:
Thing.objects.using('appropriate_database').all()
有沒有辦法避免使用的using
,使用戶/數據庫關係隱含不知何故?
同一型號我有以下問題:不同的數據庫與Django的
我需要爲每個用戶相同型號不同的數據庫(或一組用戶)。我有辦法找出用戶與哪個數據庫相關。問題是我總是必須在每個查詢中使用using
方法。
例如:
Thing.objects.using('appropriate_database').all()
有沒有辦法避免使用的using
,使用戶/數據庫關係隱含不知何故?
我們做到了!讓我解釋一下。
我們編寫了一個自定義中間件,並將其註冊爲settings.py文件中的中間件類。
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'our.custom.middleware.Class',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
該中間件具有創建線程變量(from threading import local
)來存儲相應的數據庫名稱爲當前用戶一個process_request方法。由於每個請求都由不同的線程處理,我們知道我們的變量值不會被另一個線程意外更改。
下一步是創建一個Database Router並註冊它。
DATABASE_ROUTERS = ('our.custom.database.Router',)
注意:默認settings.py
沒有DATABASE_ROUTERS
變量。你必須創建它。
我們的定製Router
與和db_for_write
具有相同的實現。這些方法唯一做的就是返回存儲在我們線程變量上的數據庫名稱。
就是這樣。現在我們不必每次需要恢復或保存模型對象時都調用using
。
聽起來像一個不好的設計,不能擴展到我。每次添加用戶時都必須複製模式。
一個更好的設計會有一個表USER與每個用戶需要的實體進行一對多和多對多的關係。
你好,@duffymo。我很欣賞你對設計的想法。當你說設計不能擴展時,也許你是對的。但並不是每個用戶都會創建一個新的數據庫,因爲它可以鏈接到現有的數據庫。我不認爲我明白你的意思。你的意思是我應該有一個與數據庫上的EVERY表有關係的User對象?我不明白這是如何改善的。你能提供更多細節嗎? – Bonifacio2
不是每個表格,只是包含用戶特定數據的表格。這是一個改進,因爲您可以通過插入新數據而不是修改模式來添加新用戶。您將消費應用程序從模式更改中屏蔽掉。這是關係數據庫的用途。 – duffymo
你可以在你的模型創建第二個經理:
class MyModelManager(models.Manager):
def get_query_set(self):
return super(MyModelManager, self).get_query_set().using('appropriate_database')
class MyModel(models.Model):
# "objects" is the default manager
objects_db2 = MyModelManager()
field1 = models.CharField(...)
class MyModel2(models.Model):
objects_db2 = MyModelManager()
...
然後使用查詢MyModel.objects_db2.filter(...).order_by(...)...
你好,@ Ricola3D。感謝您的回答。我認爲,使用您提供的解決方案,我只會切換問題。由於我不需要指定數據庫,但是我將指定模型管理器。 – Bonifacio2
你試圖解決什麼問題? –
我只是在尋找一種方法來連接到不同的數據庫,而不必明確地說我想要連接到哪個數據庫,從當前登錄的用戶推導出正確的數據庫。 – Bonifacio2