gpt4 book ai didi

python - 在 Django 中注释现有模型对象

转载 作者:太空宇宙 更新时间:2023-11-04 11:07:40 25 4
gpt4 key购买 nike

有没有办法使用类似 Django 的 annotate 的东西?方法,但对于现有模型实例的集合而不是查询集?

假设我有一个这样的模型(所有不相关的细节都被删除):

class Node(Model):
parent = ForeignKey('self', related_name='children')

如果我正在获取一些节点并希望每个节点的子节点计数,我可以这样做:

nodes = Node.objects.filter(some_filter=True).annotate(child_count=Count('children'))
for node in nodes:
print(node.child_count)

但是如果我已经有了一个 Node 对象集合,而不是一个查询集呢?这样做的天真方式会受到 N+1 query problem 的影响。 ,这对于性能来说是 Not Acceptable :

for node in nodes:
print(node.children.count()) # executes a separate query for each instance

我基本上想要相当于 prefetch_related_objects 的注释.我正在想象这样的事情:

nodes = list(Node.objects.filter(some_filter=True))
annotate_objects(nodes, child_count=Count('children'))
for node in nodes:
print(node.child_count)

Django 中是否内置了类似的东西?浏览文档对我来说并没有取得成果。

最佳答案

我最终编写了一个辅助函数来实现我想象中的 API:

from collections import defaultdict

def annotate_objects(model_instances, *args, **kwargs):
"""
The annotation equivalent of `prefetch_related_objects`: works just like the
queryset `annotate` method, but operates on a sequence of model instances
instead of a queryset.
"""

if len(model_instances) == 0:
return

# Group instances by model class (since you can hypothetically pass
# instances of different models).
instances_by_model_class = defaultdict(list)
for instance in model_instances:
instances_by_model_class[type(instance)].append(instance)

for Model, instances in instances_by_model_class.items():
pks = set(instance.pk for instance in instances)
queryset = Model.objects.filter(pk__in=pks).annotate(*args, **kwargs)
annotation_keys = list(queryset.query.annotations.keys())
all_annotations = queryset.values(*annotation_keys)
for instance, annotations in zip(instances, all_annotations):
for key, value in annotations.items():
setattr(instance, key, value)

使用:

annotate_objects(nodes, child_count=Count('children'))
for node in nodes:
print(node.child_count)

关于python - 在 Django 中注释现有模型对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59058486/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com