我在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