Same situation as Django prefetch_related children of children but different question:
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, null=True)
A Node can have several children, and each of these children can have its own children.
I would like to do something like that:
def cache_children(node):
for child in node.children.all():
cache_children(child)
root_node = Node.objects.prefetch_related('children').get(pk=my_node_id)
all_nodes = Node.objects.all() # get all the nodes in a single query
# Currently: hit database for every loop
# Would like: to somehow use the already loaded data from all_nodes
cache_children(root_node)
As I already grabbed all the nodes in the all_nodes
query, I would like to reuse the cached data from this query instead of performing a new one each time.
Is there any way to achieve that?
Data in a tree like structure is not really well suited for a relational database, there are however some strategies to solve this - see the chapter on tree implemenations in the docs of django-treebeard.
If your tree isn't too big, you could totally store the tree in a python dict and cache the results.
Example (untested - adapt the data structure to your liking...):
I managed to make it work this way and populate the whole tree with 2 db calls:
I discovered the
_prefetched_objects_cache
attribute thanks to this answer: Django: Adding objects to a related set without saving to DB