Django prefetch_related дети детей - PullRequest
2 голосов
/ 17 марта 2019

У меня есть модель 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 Ответ

1 голос
/ 17 марта 2019

Согласно документам вы можете сделать это:

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')))
...