你可以这样接近:
qs = A.objects.prefetch_related(Prefetch(
'related',
queryset=A.objects.only('pk'),
to_attr='related_insts')).in_bulk(my_list_of_pks)
这将给出从当前对象的 pks 到实例本身的映射,因此您可以按如下方式迭代:
for pk, inst in qs.iteritems():
related_ids = (related.pk for related in inst.related_insts)
或者给定一个实例,您可以像这样进行快速查找:
related_ids = (related.pk for related in qs[instance.pk]).
此方法将实例 ID 映射到相关 ID(间接),因为您特别请求了字典。如果您不进行查找,则可能需要以下内容:
qs = A.objects.prefetch_related(Prefetch(
'related',
queryset=A.objects.only('pk'),
to_attr='related_insts')).filter(pk__in=my_list_of_pks)
for inst in qs:
related_ids = (related.pk for related in inst.related_insts)
您可能会注意到使用only 仅从数据库中提取pks。有一个open ticket 允许在预取查询中使用values 和(我认为)values_list。这将允许您执行以下操作。
qs = A.objects.prefetch_related(Prefetch(
'related',
queryset=A.objects.values_list('pk', flat=True),
to_attr='related_ids')).filter(pk__in=my_list_of_pks)
for inst in qs:
related_ids = inst.related_ids
您当然可以进一步优化,例如在主查询集上使用 qs.only('related_insts'),但请确保您不对这些实例做任何事情——它们本质上只是用于保存您的相关 ID 的昂贵容器。
我相信这是目前最好的(没有自定义查询)。要达到您想要的效果,需要做两件事:
- 上述功能已实现
-
values_list 可与 Prefetch to_attr 一起使用,就像对注释一样。
有了这两件事(并继续上面的示例),您可以执行以下操作以获得您所要求的内容:
d = qs.values_list('related_ids', flat=True).in_bulk()
for pk, related_pks in d.items():
print 'Containing Objects %s' % pk
print 'Related objects %s' % related_pks
# And lookups
print 'Object %d has related objects %s' % (20, d[20])
我省略了一些解释事情的细节,但从文档中应该很清楚。如果您需要任何说明,请不要犹豫!