这两个是一样的
MyClass.objects.prefetch_related('relation')
MyClass.objects.prefetch_related(
Prefetch('relation', to_attr='relation_as_list')
)
您可以使用 Prefetch 对象进一步控制预取操作 (docs)
只有在需要细化prefetch_related 的结果时才需要Prefetch 对象。例如,您可能不需要每个relation,而是需要特定的,因此您可以优化预取查询。
建议在过滤预取结果时使用 to_attr,因为它比将过滤结果存储在相关管理器的缓存中更不模糊 (docs)
to_attr 不会提供额外的性能提升,它允许使Prefetch 关系不那么模糊,并且可以使用不同的查询集预取相同的关系。
MyClass.objects.prefetch_related(
Prefetch('same_relation', queryset=queryset_one, to_attr='relation_set_one')
Prefetch('same_relation', queryset=queryset_two, to_attr='relation_set_two')
)
如果您使用不同的Prefetch 对象预取相同的关系,则每个对象都会有一个额外的查询。生成的预取 QuerySet 将存储在一个列表中,但结果不是您假设为 relation_as_list 的列表。它们是查询集。在您的示例中,可以使用all() 访问这两个关系,例如my_obj.relation_as_list.all() 和my_obj.relation.all()
关于性能提升
总之,prefetch_related 在一个(额外的)数据库命中中获取相关对象,这是性能提升的来源。 Prefetch objects 让您可以进一步细化这个 DB 调用。
for item in yourmodel.object.all():
for a_relation in item.relation.all():
do_something(a_relation)
# WITHOUT PREFETCH RELATED YOU'D HIT DB EVERY TIME!!
# IMAGINE IF YOU HAD TONS OF ITEMS
# THIS WILL HAVE 2 DB HITS
for item in yourmodel.object.prefetch_related('relation').all().:
for a_relation in item.relation.all():
do_something(a_relation)