Django-从缓存的查询填充模型实例相关字段 [英] Django - Populate model instance related field from cached query

查看:140
本文介绍了Django-从缓存的查询填充模型实例相关字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

与Django prefetch_related孩子有关的孩子情况相同,但问题不同:

Same situation as Django prefetch_related children of children but different question:

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

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.

我想做这样的事情:

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)  

因为我已经抓住了所有节点在 all_nodes 查询中,我想重用此查询中的缓存数据,而不是每次都执行一个新的。

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.

有什么方法可以实现?

推荐答案

我管理过使其以这种方式工作,并用2个db调用填充整个树:

I managed to make it work this way and populate the whole tree with 2 db calls:

def populate_prefetch_cache(node, all_nodes):
    children = [child for child in all_nodes if child.parent_id==node.id]

    # will not have the attribute if no prefetch has been done
    if not hasattr(node, '_prefetched_objects_cache'):
        node._prefetched_objects_cache = {}

    # Key to using local data to populate a prefetch!
    node._prefetched_objects_cache['children'] = children
    node._prefetch_done = True

    for child in node.children.all():
        populate_prefetch_cache(child , all_nodes )


all_nodes = list(Node.objects.all())  # Hit database once
root_node = Node.objects.get(pk=my_node_id)  # Hit database once

# Does not hit the database and properly populates the children field
populate_prefetch_cache(root_node, all_nodes)

由于以下答案,我发现了 _prefetched_objects_cache 属性: Django:将对象添加到一个相关的集合中而不保存到数据库中

I discovered the _prefetched_objects_cache attribute thanks to this answer: Django: Adding objects to a related set without saving to DB

这篇关于Django-从缓存的查询填充模型实例相关字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆