表名小寫_set.all()再根據欄位過濾
阿新 • • 發佈:2021-08-04
orm - 為什麼django的prefetch_related()只能用於all()而不能用於filter()?
假設我有這個模型:
class PhotoAlbum(models.Model): title = models.CharField(max_length=128) author = models.CharField(max_length=128) class Photo(models.Model): album = models.ForeignKey('PhotoAlbum') format = models.IntegerField()
現在,如果我想有效地檢視相簿子集中的一部分照片。 我這樣做:
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set") for a in someAlbums: somePhotos = a.photo_set.all()
這隻做了兩個查詢,這是我所期望的(一個是獲得專輯,然後是一個像`SELECT * IN photos WHERE photoalbum_id IN()。
一切都很棒。
但如果我這樣做:
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set") for a in someAlbums: somePhotos = a.photo_set.filter(format=1)
然後它用WHERE format = 1
進行了大量的查詢! 我做錯了什麼或django不夠聰明,意識到它已經取出所有的照片並可以在python中過濾它們? 我發誓我在文件中的某個地方讀到它本應該這樣做......
在Django 1.6及更早版本中,無法避免額外的查詢。 prefetch_related
呼叫有效地快取了查詢集中每個專輯的filter(spicy=True)
a.photoset.filter(format=1)
是一個不同的查詢集,因此您將為每個專輯生成一個額外的查詢。
這在prefetch_related
文件中有解釋。 prefetch_related
相當於filter(spicy=True)
。
請注意,您可以通過在python中過濾照片來減少數量或查詢:
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set") for a in someAlbums: somePhotos = [p for p in a.photo_set.all() if p.format == 1]
在Django 1.7中,有一個prefetch_related
物件,允許您控制prefetch_related
的行為。
from django.db.models import Prefetch someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related( Prefetch( "photo_set", queryset=Photo.objects.filter(format=1), to_attr="some_photos" ) ) for a in someAlbums: somePhotos = a.some_photos每天逼著自己寫點東西,終有一天會為自己的變化感動的。這是一個潛移默化的過程,每天堅持編編故事,自己不知不覺就會擁有故事人物的特質的。 Explicit is better than implicit.(清楚優於含糊)