【问题标题】:Get only one related object from Django queryset从 Django 查询集中只获取一个相关对象
【发布时间】:2016-09-05 16:19:42
【问题描述】:

我正在尝试在 Django 中优化类似提要的查询,在该查询中,我得到了我关注的用户评论的独特项目。

        queryset_comments = Item.objects.distinct() \
        .prefetch_related('comments', 'comments__user') \
        .filter(comments__user__in=self.request.user.following.all()) \
        .prefetch_related(
            Prefetch('comments', queryset=Comment.objects.filter(
                user__in=self.request.user.following.all()
            ).order_by('-created_on'), to_attr='activity')
        ) \
        .all()

这给了我一个相关的activity 对象,其中包含我关注的用户创建的所有 cmets 的列表,最近的评论在前。现在我只需要第一个,所以我循环其他查询集并设置我需要的值:

        for item in queryset_comments:
            item.feed_user = item.activity[0].user
            item.feed_date = item.activity[0].created_on
            item.feed_activity = 'commented'

但是这个循环只需要大约 500 个项目就需要超过 2 秒...我尝试使用切片进行预取(通过将 [0].first() 添加到 Prefetch 查询集,但这两种方法都不支持by Django ORM。

有什么建议可以加快速度吗?

【问题讨论】:

  • 您是否已经尝试过earliestlatest
  • 尝试在for 循环之后使用latest_activity = item.activity.first(),然后使用此latest_activity 对象在item 上设置其他值。
  • @2ps: 得到与我使用切片时相同的错误:AttributeError: 'Item' object has no attribute '_add_hints'
  • @Rahul:item.activity 是一个列表,我得到AttributeError: 'list' object has no attribute 'first'。我试过latest_activity = item.activity[0],它可以工作,但需要同样的时间。
  • 最后,我将进行缓存/redis 非规范化以加快提要检索。

标签: python django


【解决方案1】:

有一个类似的question here 让我得出了同样的结论。

我建议不要使用prefetch_related,而是完成查询集的工作,直到它准备好执行数据库查询。甚至可能是分页的,所以你只有 20 或 50 个对象。

然后列出所有 Item.pk 值并自己获取相关的“每个项目一条评论”(使用 Max('created_on') )。

prefetch_related 相同,但具有更多控制权。

【讨论】:

    猜你喜欢
    • 2014-11-05
    • 1970-01-01
    • 2016-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    相关资源
    最近更新 更多