假设我有这个模型:

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

这只会执行两个查询,这是我所期望的(一个是获取相册,另一个是在photoalbum_id位于()的照片中 Select *).

一切都很好.

但如果我这么做:

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)是一个不同的查询集,因此您将 for each 专辑生成一个额外的查询.

这在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个文档.

Django相关问答推荐

APIView查询未返回任何结果

Django没有';t显示黄页

Django ImproperlyConfigured: AUTH_USER_MODEL指向尚未安装的模型'users.User'

按下按钮刷新在html文件中显示的变量

有没有办法在Django中按需/点击仅获取和序列化一部分数据以提高性能?

Django rest framework, AttributeError: 'str' object has no attribute 'data' 无法使用表单上传图片

Playframework 和 Django

初始填充 Django 表单

如何让两个模型相互引用 Django

Django 视图 - 首先从调用应用程序的目录加载模板

Django error:不能分配必须是实例

手动触发 Django 邮件错误报告

Django - 如何从模型中 Select 特定列?

Heroku - 在 Django 应用程序中处理静态文件

在 Django 应用程序之间共享模型

Django UrlResolver,在运行时添加 url 进行测试

在 Django 中使用邮箱地址或用户名登录用户

django 在 unittest 测试中设置环境变量

升级到 Django 1.8 后提供的固定默认值

Django:如何从模板中识别调用视图?