Django查询关联视频报QuerySet无videos/videos_set属性错误
报错原因
- 核心问题:你代码中
curriculum = Curriculum.objects.filter(course=course)拿到的不是单个Curriculum模型实例,是filter()返回的QuerySet类型(即符合查询条件的多条Curriculum记录的集合)。反向关联属性(包括你配置的related_name="videos"、Django默认生成的video_set)仅能在单个模型实例上调用,直接在QuerySet集合上调用自然会触发属性不存在的报错。哪怕filter查询结果只有1条记录,返回值依然是QuerySet类型,不会自动变成单个实例。 - 隐藏逻辑问题:未登录分支中写的
course.videos.all()、Video.objects.filter(course=course)逻辑本身不成立,你的Video模型外键是关联Curriculum而非Course,Course模型没有配置直达Video的关联关系,这部分代码运行时也会报错。
修复方案
你的模型层级是Course 1对多 Curriculum 1对多 Video,即一个课程对应多个大纲,每个大纲对应多个视频,按以下步骤修正即可:
1. 修正基础查询逻辑
把原来直接在QuerySet上调关联属性的写法替换为跨关联查询,性能更高也不会触发类型错误:
# 已登录、未登录分支都先查当前课程下的所有大纲 curriculums = Curriculum.objects.filter(course=course) # 跨关联查询所有属于这些大纲的视频,按序列号排序 videos = Video.objects.filter(curriculum__in=curriculums).order_by("serial_number") video_count = videos.count() lectures = videos.count()
如果你的页面需要按大纲分组展示视频,可以加预加载减少数据库查询,遍历单个大纲实例时再调用反向关联:
# 预加载所有大纲关联的视频,避免循环查询 curriculums = Curriculum.objects.filter(course=course).prefetch_related("videos") # 遍历拿到单个大纲实例后,就可以正常调用.videos取关联视频 for item in curriculums: item_videos = item.videos.all().order_by("serial_number")
2. 修正单条视频查询逻辑
原来的get_or_create直接传入QuerySet作为curriculum参数会触发参数类型错误,需要调整查询条件,同时给非空字段补默认值避免新建记录时触发约束报错:
# 两个分支的单条视频查询都替换为以下逻辑 video, created = Video.objects.get_or_create( serial_number=serial_number, curriculum__in=curriculums, defaults={ "curriculum": curriculums.first(), "video_id": "", "title": f"第{serial_number}讲" } )
3. 额外注意点
你已经在Video的curriculum外键上配置了related_name="videos",反向关联查询直接用.videos即可,不需要再用Django默认生成的video_set,二者同时使用反而会造成关联命名冲突。
内容的提问来源于stack exchange,提问作者Destiny Franks
相关产品推荐
相关产品推荐

