假设我有这个模型:
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
调用有效地缓存了结果a.photoset.all()
对于查询集中的每个专辑。然而,a.photoset.filter(format=1)
是一个不同的查询集,因此您将为每个专辑生成一个额外的查询。
这在prefetch_related文档。这filter(format=1)
相当于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()允许您控制行为的对象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
有关如何使用的更多示例Prefetch
对象,请参阅prefetch_related docs.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)