Django prefetch_related children of children

2019-07-19 04:02发布

I have a model Node that looks something like that:

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

A Node can have several children, and each of these children can have its own children.

If I do:

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

The database gets hit every time I try to access the children of a child.

How could I make it so that it gets the node, its children, the children of its children, etc, in a single database query?

1条回答
看我几分像从前
2楼-- · 2019-07-19 04:47

According to the docs you can do this:

Restaurant.objects.prefetch_related('pizzas__toppings')

This will prefetch all pizzas belonging to restaurants, and all toppings belonging to those pizzas. This will result in a total of 3 database queries - one for the restaurants, one for the pizzas, and one for the toppings.

or you can use the Prefetch object to further control the prefetch operation.

from django.db.models import Prefetch

Restaurant.objects.prefetch_related(Prefetch('pizzas__toppings'), queryset=Toppings.objects.order_by('name')))
查看更多
登录 后发表回答