我有一个模型媒体,它与模型UserMedia(用户评分)有关系。还有一个与问题相关的名为UserMatchScore(用户匹配分数)的模型。
在一个视图中,我正在查询媒体表,在该视图中,有一个选项只能获取我的比赛已评级但我尚未评级的媒体。还会根据我和我的比赛的子集(并非所有对媒体进行过评分的用户)返回平均收视率。我用注释来做。
我要做的是过滤媒体表中没有被评估但我的比赛获得评估的元素,这很简单,但是仅完成一半的工作。返回所有我尚未评级的媒体,但我的比赛已评级,但是关系字段UserMedia仍包含所有评级,该媒体未过滤,因此无法计算我的比赛子集的平均评级。 这是我正在描述的查询:
queryset = models.Media.objects
queryset = queryset.filter(
Q(usermedia__user__id__in=my_matches) & ~Q(usermedia__user=user)
)
获得预期结果的唯一方法是循环查询集并过滤UserMedia关系的每个元素,但这太慢了,因此必须使用数据库查询来完成。
for el in queryset:
el.usermedia_set.filter(~Q(user=user)).filter(user=my_matches)
有人知道如何使用Django ORM做到这一点吗?
答案 0 :(得分:3)
使用Prefetch
,可以使用预先过滤的查询集获取关系的相关对象(对于多对多和反向外键关系):
queryset = queryset.filter(
Q(usermedia__user__id__in=my_matches) & ~Q(usermedia__user=user)
)
prefetch = UserMedia.objects.filter(user_id__in=my_matches).exclude(user=user)
queryset = queryset.prefetch_related(
Prefetch('usermedia_set', prefetch, to_attr='filtered_usermedia')
)
for el in queryset:
for usermedia in el.filtered_usermedia:
# iterate over the filtered usermedia
# without any additional queries
calculate_something(usermedia)
请注意,与之前针对主查询集中的每个对象的一个附加查询相比,这将导致一个附加查询来预取所有相关对象(因此,总共两个查询,无论您获取多少行)。