我在Django(使用Postgres)中有以下模型模式。Django:快速检索manyToMany字段的ID
class A(Models.model):
related = models.ManyToManyField("self", null=True)
给出的一个QuerySet,我想在查询集尽可能快地恢复一个字典映射的A
每个实例的id
开发它related
实例列表越好。
我肯定可以迭代每个A并查询相关字段,但是有没有更优化的方法?
我在Django(使用Postgres)中有以下模型模式。Django:快速检索manyToMany字段的ID
class A(Models.model):
related = models.ManyToManyField("self", null=True)
给出的一个QuerySet,我想在查询集尽可能快地恢复一个字典映射的A
每个实例的id
开发它related
实例列表越好。
我肯定可以迭代每个A并查询相关字段,但是有没有更优化的方法?
根据你有三个实例。您可以使用values_list
方法来检索结果,并从此结果中获取related
实例的ID。 我使用pk
字段做我的过滤器,因为我不知道你的方案,但你可以使用任何东西,只需要一个QuerySet
。
>>> result = A.objects.filter(pk=1)
>>> result.values('related__id')
[{'id': 2}, {'id': 3}]
>>> result.values_list('related__id')
[(2,), (3,)]
>>> result.values_list('related__id', flat=True)
[2, 3]
这就是我一直在做的,但问题是我需要过滤多个'pk'(例如'A.objects.filter(pk__in = [1,2,6])'')。我想要一个列表清单,其中第n个内部列表像这里的'values_list',但对应于第n个'pk'。 –
如果您已经有单个模型实例,您也可以执行instance.related.values('id',flat = True)。 – alexcasalboni
你可以得到非常接近这样的:
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
的只从DB拉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')
,但要确保你没有做任何与这些instances--他们基本上只是昂贵的容器来保存你的related_ids。
我相信这是现在最好的(没有自定义查询)。为了得到你想要什么,还需要两两件事:
values_list
由像它的注解与预取to_attr
工作。有了这两样东西(并继续上面的例子),你可以做到以下几点得到正是你要求:
d = qs.values_list('related_ids', flat=True).in_bulk()
for pk, related_pks in d:
print 'Containing Objects %s' % pk
print 'Related objects %s' % related_pks
# And lookups
print 'Object %d has related objects %s' % (20, d[20])
我已经离开了一些细节解释的事情,但它应该从文档中很清楚。如果您需要澄清,请不要犹豫!
你有没有得到这个解决方案? – cazgp