Django prefetch_related孩子的孩子

时间:2019-03-16 21:17:56

标签: django django-orm

我有一个模型Node,看起来像这样:

class Node(models.Model):
    parent = models.ForeignKey('self', related_name='children', on_delete=models.CASCADE)

一个节点可以有几个孩子,每个孩子可以有自己的孩子。

如果我这样做:

def show_child(node):
    for child in node.children.all():
        show_child(child)

root_node = Node.objects.prefetch_related('children').get(pk=my_node_id) # hit database twice, as expected
print("Now testing queries")
root_node.children.all()  # no hit
root_node.children.all()  # no hit
root_node.children.all()  # no hit
root_node.children.all()  # no hit
print("Test 2")
show_child(root_node)  # hit database for every loop except the first

每次我尝试访问一个孩子的孩子时,数据库都会受到攻击。

我如何做到这一点,以便它在单个数据库查询中获取节点,其子节点,其子节点等?

1 个答案:

答案 0 :(得分:1)

根据docs,您可以执行以下操作:

Restaurant.objects.prefetch_related('pizzas__toppings')

这将预取所有属于餐厅的比萨饼,以及属于这些比萨饼的所有浇头。这将导致总共3个数据库查询-一个针对餐厅,一个针对披萨和一个针对浇头。

或者您可以使用Prefetch对象进一步控制预取操作。

from django.db.models import Prefetch

Restaurant.objects.prefetch_related(Prefetch('pizzas__toppings'), queryset=Toppings.objects.order_by('name')))