Django4.0 多數(shù)據(jù)庫-手動選擇數(shù)據(jù)庫

2022-03-16 17:38 更新

Django也提供允許在代碼中完全控制數(shù)據(jù)庫的API。手動指定數(shù)據(jù)庫分配將優(yōu)先于路由分配的數(shù)據(jù)庫。

手動為查詢集選擇數(shù)據(jù)庫

你可以在查詢集鏈的任一點為查詢集選擇數(shù)據(jù)庫。調(diào)用查詢集上的 ?using()? 就可以獲取使用指定數(shù)據(jù)庫的其他查詢集。
?using()? 使用單一參數(shù):你打算進行查詢的數(shù)據(jù)庫別名。比如:

>>> # This will run on the 'default' database.
>>> Author.objects.all()

>>> # So will this.
>>> Author.objects.using('default').all()

>>> # This will run on the 'other' database.
>>> Author.objects.using('other').all()

為保存選擇數(shù)據(jù)庫

使用 ?using ?關鍵字來 ?Model.save()? 到指定的數(shù)據(jù)保存的數(shù)據(jù)庫。
比如,要保存對象到 ?legacy_users數(shù)據(jù)庫,你應該這樣寫:

>>> my_object.save(using='legacy_users')

如果你沒有指定 ?using?,?save()? 方法將保存到路由的默認數(shù)據(jù)庫分配。

將對象從一個數(shù)據(jù)庫移動到另一個

如果已經(jīng)保存實例到數(shù)據(jù)庫,它可能使用 ?save(using=...)? 作為遷移實例到新數(shù)據(jù)庫的方法。然而,如果沒有使用適合的步驟,這可能會產(chǎn)生意想不到的結(jié)果。
考慮下面的例子:

>>> p = Person(name='Fred')
>>> p.save(using='first')  # (statement 1)
>>> p.save(using='second') # (statement 2)

在語句1,新的 ?Person ?對象保存在 ?first ?數(shù)據(jù)庫。這一次,?p ?沒有主鍵,因此 Django 發(fā)出了一個SQL ?INSERT ?語句。這會創(chuàng)建主鍵,并且 Django 分配那個主鍵到 ?p?。
在語句2中進行保存時,?p ?也有主鍵值,Django 將試圖在新的數(shù)據(jù)庫上使用主鍵。如果主鍵值未在 ?second ?數(shù)據(jù)庫中使用,那么將不會有任何問題——對象將被拷貝到新數(shù)據(jù)庫。
然而,如果 ?p ?的主鍵已經(jīng)在 ?second ?數(shù)據(jù)庫上使用,那么當保存 ?p ?的時候, ?second ?數(shù)據(jù)庫中存在的對象將被覆蓋。
可以通過兩種方式避免這種情況。首先,可以清理實例主鍵。如果對象沒有主鍵,那么 Django 將它作為新對象來處理,避免在 ?second ?數(shù)據(jù)庫上造成任何數(shù)據(jù)丟失:

>>> p = Person(name='Fred')
>>> p.save(using='first')
>>> p.pk = None # Clear the primary key.
>>> p.save(using='second') # Write a completely new object.

第二個辦法就是使用 ?force_insert ?選項來 ?save()? ,確保 Django 執(zhí)行了 SQL ?INSERT ?:

>>> p = Person(name='Fred')
>>> p.save(using='first')
>>> p.save(using='second', force_insert=True)

這將確保 ?Fred ?在兩個數(shù)據(jù)庫上擁有同一個主鍵。當試著在 ?second ?上保存時,如果主鍵已經(jīng)保存,那么將會引發(fā)一個錯誤。

選擇要刪除的數(shù)據(jù)庫

默認情況下,用來刪除現(xiàn)有對象的調(diào)用將在用于首先檢索對象的同一數(shù)據(jù)庫上執(zhí)行:

>>> u = User.objects.using('legacy_users').get(username='fred')
>>> u.delete() # will delete from the `legacy_users` database

指定將要刪除模型的數(shù)據(jù)庫,傳遞 ?using ?關鍵字參數(shù)到 ?Model.delete()? 方法。這個參數(shù)的工作方式與用關鍵字參數(shù) ?save()? 是一樣的。
例如,如果你正在從 ?legacy_users ?遷移用戶到 ?new_users ?數(shù)據(jù)庫,你可以使用這些命令:

>>> user_obj.save(using='new_users')
>>> user_obj.delete(using='legacy_users')

使用多個數(shù)據(jù)庫管理器

在管理器上使用 ?db_manager()? 方法來讓管理員訪問非默認數(shù)據(jù)庫。
比如,假設有一個自定義管理器方法來觸發(fā)數(shù)據(jù)庫——?User.objects.create_user()?。因為 ?create_user()? 是一個管理器方法,不是 ?QuerySet ?方法,你不能操作 ?User.objects.using('new_users').create_user()? 。(?create_user()? 方法只適用 ?User.objects? ,即管理器,而不是來自管理器上的 ?QuerySet ?。)解決方案是使用 ?db_manager()? ,像這樣:

User.objects.db_manager('new_users').create_user(...)

?db_manager()? 返回綁定到指定數(shù)據(jù)庫的管理器副本。

將 get_queryset() 和多個數(shù)據(jù)庫使用

如果在管理器上覆蓋了 ?get_queryset()? ,請確保在父類上調(diào)用這個方法使用 ?super()? 或者在管理器(包含使用的數(shù)據(jù)庫的名字)上適當處理 ?_db? 屬性。
比如,如果你想從 ?get_queryset? 方法返回自定義的 ?QuerySet ?類,你可以這樣做:

class MyManager(models.Manager):
    def get_queryset(self):
        qs = CustomQuerySet(self.model)
        if self._db is not None:
            qs = qs.using(self._db)
        return qs


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號