You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django无外键关联时,如何跨表注解统计影片制片方总浏览量?

问题描述

现有三个Django模型/数据表:

class Stats:
    obj_type = models.TextField(blank=True, db_index=True)
    obj_id = models.PositiveIntegerField(blank=True, null=True, db_index=True)
    views_count = models.IntegerField(blank=True, null=True, default=0)

class Movie:
    title = models.TextField(blank=True)
    producer = models.TextField(blank=True)

class Cartoon:
    title = models.TextField(blank=True)
    producer = models.TextField(blank=True)

Stats表约有150万条数据,其中obj_type字段存储'Movie'或'Cartoon'字符串,对应关联Movie或Cartoon表的记录(无外键关联)。

需要获取Movie表中所有制片方的列表,以及每个制片方对应的总浏览量(统计依据为Stats表中对应Movie的views_count之和),示例输出:

Walt Disney: 17055    # 所有制片方为'Walt Disney'的Movie的总浏览量
Netflix: 15046
etc.

希望实现类似“浏览量字段在Movie表中”时的简洁写法:

views = Movie.objects.values('producer').annotate(count=Sum('views_count'))
最优实现方案

直接通过Django ORM构造数据库层面的关联查询,避免在Python内存中处理大量数据,保证效率:

from django.db.models import Sum

result = Movie.objects.filter(
    id__in=Stats.objects.filter(obj_type='Movie').values('obj_id')
).values('producer').annotate(total_views=Sum('stats__views_count')).order_by('-total_views')

原理说明

  1. 先筛选Stats表中obj_type='Movie'的记录,获取对应的obj_id(即Movie的id)
  2. 关联Movie表,按producer分组,统计每组关联的Stats记录中views_count的总和
  3. 利用现有索引:Stats的obj_type和obj_id已加索引,Movie的id是主键索引,数据库会高效执行关联查询

输出处理

如果需要直接输出示例格式的结果,可以遍历查询集:

for item in result:
    print(f"{item['producer']}: {item['total_views']}")

性能优化提示

  • 若Movie表的producer字段查询频繁,可添加db_index=True,进一步提升分组统计效率
  • 绝对避免Python循环逐条关联查询(比如先查所有Movie,再逐个查对应Stats求和),这种方式会产生百万级查询,性能极差

内容的提问来源于stack exchange,提问作者Edmond

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 19:12:36