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

在Django中如何实现每个频道仅查询3条关联视频?

解决方案

要实现每个频道取3条最高per_sec_views的视频,你可以用Django的窗口函数或者子查询+聚合的方式,以下是具体实现:

方法一:使用窗口函数(Django 2.0+ 推荐)

窗口函数可以给每个频道内的视频按播放量排序并生成行号,之后筛选行号≤3的结果即可:

from django.db.models import Window, F
from django.db.models.functions import RowNumber

def each_channel_three_videos(request):
    # 给每个频道的视频按per_sec_views降序生成行号
    videos = YTVideo.objects.select_related('channel')\
        .filter(channel__category__slug='vlogs')\
        .annotate(
            row_num=Window(
                expression=RowNumber(),
                partition_by=F('channel_id'),
                order_by=F('per_sec_views').desc()
            )
        )\
        .filter(row_num__lte=3)  # 只保留每个频道前3条

    context = {
        'videos': videos,
    }
    return render(request, 'videos.html', context)

说明:

  • partition_by=F('channel_id'):按频道ID分组
  • order_by=F('per_sec_views').desc():每组内按per_sec_views降序排序
  • row_num__lte=3:筛选每组的前3条数据

方法二:使用子查询(兼容低版本Django)

如果你的Django版本较低不支持窗口函数,可以用子查询+聚合的方式,先获取每个频道的前3条视频ID,再批量查询:

from django.db.models import Subquery, OuterRef

def each_channel_three_videos(request):
    # 子查询:获取单个频道的前3条视频ID
    top_videos_subquery = YTVideo.objects.filter(
        channel_id=OuterRef('channel_id')
    ).order_by('-per_sec_views')[:3].values_list('id', flat=True)

    # 筛选所有在子查询结果里的视频
    videos = YTVideo.objects.select_related('channel')\
        .filter(channel__category__slug='vlogs')\
        .filter(id__in=Subquery(top_videos_subquery))\
        .order_by('channel_id', '-per_sec_views')  # 按频道+播放量排序

    context = {
        'videos': videos,
    }
    return render(request, 'videos.html', context)

说明:

  • OuterRef('channel_id'):引用外部查询的频道ID,实现每个频道单独查询前3条
  • id__in=Subquery(...):过滤出所有符合条件的视频
  • 最后order_by可以让结果按频道分组展示,方便前端渲染

前端渲染建议

如果需要按频道分组展示视频,可以在视图里把结果整理成字典:

from collections import defaultdict

def each_channel_three_videos(request):
    # 先按上面任意一种方法获取videos
    videos_by_channel = defaultdict(list)
    for video in videos:
        videos_by_channel[video.channel].append(video)
    
    context = {
        'videos_by_channel': videos_by_channel,
    }
    return render(request, 'videos.html', context)

前端模板可以这样遍历:

{% for channel, videos in videos_by_channel.items %}
    <h3>{{ channel.channel_title }}</h3>
    <ul>
        {% for video in videos %}
            <li>{{ video.title }}</li>
        {% endfor %}
    </ul>
{% endfor %}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:50:34