Python Django:快速检索许多字段的ID

Python Django:快速检索许多字段的ID,python,database,django,postgresql,m2m,Python,Database,Django,Postgresql,M2m,我在Django中有以下模型模式(带有Postgres) 给定a的查询集,我想尽快返回一个字典,将查询集中a的每个实例映射到与其相关的实例的ids列表 我当然可以遍历每个A并查询相关字段,但有没有更优化的方法?根据您有三个实例。您可以使用values\u list方法仅检索结果,并从该结果中仅获取其相关实例的ID。 我使用pk字段作为我的过滤器,因为我不知道你的方案,但你可以使用任何东西,只要是QuerySet >>> result = A.objects.filter(pk=

我在Django中有以下模型模式(带有Postgres)

给定a的查询集,我想尽快返回一个字典,将查询集中
a
的每个实例映射到与其
相关的
实例的
id
s列表


我当然可以遍历每个A并查询相关字段,但有没有更优化的方法?

根据您有三个实例。您可以使用
values\u list
方法仅检索结果,并从该结果中仅获取其
相关
实例的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]

你可以像这样靠得很近:

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。允许在预回迁查询中使用
和(我想)值列表
。这将允许您执行以下操作

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\u list
    用于预取
    到属性
    ,就像用于注释一样 有了这两件事(并继续上面的示例),您可以执行以下操作以获得您所要求的内容:

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

    我省略了一些详细的解释,但从文档中应该非常清楚。如果您需要任何澄清,请不要犹豫

    这就是我一直在做的,但问题是我需要过滤多个
    pk
    (例如
    A.objects.filter(pk\u in=[1,2,6])
    )。我想要一个列表列表,其中第n个内部列表类似于此处的
    值列表
    ,但对应于第n个
    pk
    。如果您已经有一个模型实例,您还可以执行instance.related.values('id',flat=True)。您有过解决方案吗?
    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])