【问题标题】:Query prefetched objects without using the db?不使用数据库查询预取对象?
【发布时间】:2014-10-14 17:28:53
【问题描述】:

我正在从我的数据库中获取多个具有预取关系的对象:

datei_logs = DateiLog.objects.filter(user=request.user)
                             .order_by("-pk")
                             .prefetch_related('transfer_logs')

transfer_logs指的是这个:

class TransferLog(models.Model):
  datei_log = models.ForeignKey("DateiLog", related_name="transfer_logs")
  status = models.CharField(
                    max_length=1,
                    choices=LOG_STATUS_CHOICES,
                    default='Good'
                    ) 
  server_name = models.CharField(max_length=100, blank=True, default="(no server)")
  server = models.ForeignKey('Server')

  class Meta:
    verbose_name_plural = "Transfer-Logs"

  def __unicode__(self):
    return self.server_name

现在我想获取所有状态为"Good"TransferLogs。但我想如果我这样做:

datei_logs[0].transfer_logs.filter(...)

它再次查询数据库!由于这发生在一个有许多日志条目的网站上,我最终得到了 900 个查询!

我用:

datei_logs[0].transfer_logs.count()

同样,它也会导致对数据库的大量查询!

我该怎么做才能“获取所有内容”,然后只查询一个包含所有信息的对象而不是数据库?

【问题讨论】:

    标签: python django django-1.7


    【解决方案1】:

    由于您使用的是 Django 1.7,因此您可以使用新的 Prefetch() 对象来指定要用于相关查找的查询集。

    queryset = TransferLog.objects.filter(status='Good')
    datei_logs = DateiLog.objects.filter(user=request.user)
                                 .order_by("-pk")
                                 .prefetch_related(Prefetch('transfer_logs', 
                                                            queryset=queryset,
                                                            to_attr='good_logs'))
    

    然后你可以访问datei_logs[0].good_logs并检查len(datei_logs[0].good_logs)

    如果您对多个状态感兴趣,您可以使用多个 Prefetch 对象。但是,如果您无论如何都要获取所有日志,那么您不妨坚持原来的查询,然后在 Python 中拆分日志,而不是调用 filter()

    【讨论】:

    • 但是如果我还想要坏的和中性的日志,这意味着我需要每个 Prefetch() 每个 datei_log 一个查询?这似乎仍然很多!
    • 谢谢凯文!我将您的评论添加到答案中以使其完整。
    猜你喜欢
    • 2018-09-30
    • 2010-11-13
    • 2016-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    • 2021-09-15
    相关资源
    最近更新 更多