2013-08-02 32 views
4

同一型號我有以下問題:不同的數據庫與Django的

我需要爲每個用戶相同型號不同的數據庫(或一組用戶)。我有辦法找出用戶與哪個數據庫相關。問題是我總是必須在每個查詢中使用using方法。

例如:

Thing.objects.using('appropriate_database').all() 

有沒有辦法避免使用的using,使用戶/數據庫關係隱含不知何故?

+0

你試圖解決什麼問題? –

+0

我只是在尋找一種方法來連接到不同的數據庫,而不必明確地說我想要連接到哪個數據庫,從當前登錄的用戶推導出正確的數據庫。 – Bonifacio2

回答

1

我們做到了!讓我解釋一下。

我們編寫了一個自定義中間件,並將其註冊爲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

1

聽起來像一個不好的設計,不能擴展到我。每次添加用戶時都必須複製模式。

一個更好的設計會有一個表USER與每個用戶需要的實體進行一對多和多對多的關係。

+0

你好,@duffymo。我很欣賞你對設計的想法。當你說設計不能擴展時,也許你是對的。但並不是每個用戶都會創建一個新的數據庫,因爲它可以鏈接到現有的數據庫。我不認爲我明白你的意思。你的意思是我應該有一個與數據庫上的EVERY表有關係的User對象?我不明白這是如何改善的。你能提供更多細節嗎? – Bonifacio2

+0

不是每個表格,只是包含用戶特定數據的表格。這是一個改進,因爲您可以通過插入新數據而不是修改模式來添加新用戶。您將消費應用程序從模式更改中屏蔽掉。這是關係數據庫的用途。 – duffymo

0

你可以在你的模型創建第二個經理:

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(...)...

+0

你好,@ Ricola3D。感謝您的回答。我認爲,使用您提供的解決方案,我只會切換問題。由於我不需要指定數據庫,但是我將指定模型管理器。 – Bonifacio2