W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
Django也提供允許在代碼中完全控制數(shù)據(jù)庫(kù)的API。手動(dòng)指定數(shù)據(jù)庫(kù)分配將優(yōu)先于路由分配的數(shù)據(jù)庫(kù)。
你可以在查詢集鏈的任一點(diǎn)為查詢集選擇數(shù)據(jù)庫(kù)。調(diào)用查詢集上的 ?using()
? 就可以獲取使用指定數(shù)據(jù)庫(kù)的其他查詢集。
?using()
? 使用單一參數(shù):你打算進(jìn)行查詢的數(shù)據(jù)庫(kù)別名。比如:
>>> # 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()
使用 ?using
?關(guān)鍵字來(lái) ?Model.save()
? 到指定的數(shù)據(jù)保存的數(shù)據(jù)庫(kù)。
比如,要保存對(duì)象到 ?legacy_users
數(shù)據(jù)庫(kù),你應(yīng)該這樣寫:
>>> my_object.save(using='legacy_users')
如果你沒有指定 ?using
?,?save()
? 方法將保存到路由的默認(rèn)數(shù)據(jù)庫(kù)分配。
如果已經(jīng)保存實(shí)例到數(shù)據(jù)庫(kù),它可能使用 ?save(using=...)
? 作為遷移實(shí)例到新數(shù)據(jù)庫(kù)的方法。然而,如果沒有使用適合的步驟,這可能會(huì)產(chǎn)生意想不到的結(jié)果。
考慮下面的例子:
>>> p = Person(name='Fred')
>>> p.save(using='first') # (statement 1)
>>> p.save(using='second') # (statement 2)
在語(yǔ)句1,新的 ?Person
?對(duì)象保存在 ?first
?數(shù)據(jù)庫(kù)。這一次,?p
?沒有主鍵,因此 Django 發(fā)出了一個(gè)SQL ?INSERT
?語(yǔ)句。這會(huì)創(chuàng)建主鍵,并且 Django 分配那個(gè)主鍵到 ?p
?。
在語(yǔ)句2中進(jìn)行保存時(shí),?p
?也有主鍵值,Django 將試圖在新的數(shù)據(jù)庫(kù)上使用主鍵。如果主鍵值未在 ?second
?數(shù)據(jù)庫(kù)中使用,那么將不會(huì)有任何問(wèn)題——對(duì)象將被拷貝到新數(shù)據(jù)庫(kù)。
然而,如果 ?p
?的主鍵已經(jīng)在 ?second
?數(shù)據(jù)庫(kù)上使用,那么當(dāng)保存 ?p
?的時(shí)候, ?second
?數(shù)據(jù)庫(kù)中存在的對(duì)象將被覆蓋。
可以通過(guò)兩種方式避免這種情況。首先,可以清理實(shí)例主鍵。如果對(duì)象沒有主鍵,那么 Django 將它作為新對(duì)象來(lái)處理,避免在 ?second
?數(shù)據(jù)庫(kù)上造成任何數(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.
第二個(gè)辦法就是使用 ?force_insert
?選項(xiàng)來(lái) ?save()
? ,確保 Django 執(zhí)行了 SQL ?INSERT
?:
>>> p = Person(name='Fred')
>>> p.save(using='first')
>>> p.save(using='second', force_insert=True)
這將確保 ?Fred
?在兩個(gè)數(shù)據(jù)庫(kù)上擁有同一個(gè)主鍵。當(dāng)試著在 ?second
?上保存時(shí),如果主鍵已經(jīng)保存,那么將會(huì)引發(fā)一個(gè)錯(cuò)誤。
默認(rèn)情況下,用來(lái)刪除現(xiàn)有對(duì)象的調(diào)用將在用于首先檢索對(duì)象的同一數(shù)據(jù)庫(kù)上執(zhí)行:
>>> u = User.objects.using('legacy_users').get(username='fred')
>>> u.delete() # will delete from the `legacy_users` database
指定將要?jiǎng)h除模型的數(shù)據(jù)庫(kù),傳遞 ?using
?關(guān)鍵字參數(shù)到 ?Model.delete()
? 方法。這個(gè)參數(shù)的工作方式與用關(guān)鍵字參數(shù) ?save()
? 是一樣的。
例如,如果你正在從 ?legacy_users
?遷移用戶到 ?new_users
?數(shù)據(jù)庫(kù),你可以使用這些命令:
>>> user_obj.save(using='new_users')
>>> user_obj.delete(using='legacy_users')
在管理器上使用 ?db_manager()
? 方法來(lái)讓管理員訪問(wèn)非默認(rèn)數(shù)據(jù)庫(kù)。
比如,假設(shè)有一個(gè)自定義管理器方法來(lái)觸發(fā)數(shù)據(jù)庫(kù)——?User.objects.create_user()
?。因?yàn)??create_user()
? 是一個(gè)管理器方法,不是 ?QuerySet
?方法,你不能操作 ?User.objects.using('new_users').create_user()
? 。(?create_user()
? 方法只適用 ?User.objects
? ,即管理器,而不是來(lái)自管理器上的 ?QuerySet
?。)解決方案是使用 ?db_manager()
? ,像這樣:
User.objects.db_manager('new_users').create_user(...)
?db_manager()
? 返回綁定到指定數(shù)據(jù)庫(kù)的管理器副本。
如果在管理器上覆蓋了 ?get_queryset()
? ,請(qǐng)確保在父類上調(diào)用這個(gè)方法使用 ?super()
? 或者在管理器(包含使用的數(shù)據(jù)庫(kù)的名字)上適當(dāng)處理 ?_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
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: