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

Django Admin中ORM分组统计Offer浏览量及排序问题咨询

Django Admin 实现Offer浏览量分组统计及排序方案

问题分析

你之前用annotate(Count('offer'))返回1的原因是:OfferViewCount的每条记录都对应一个offer外键,统计offer字段的数量时,每个分组内的offer都是同一个值,所以结果必然是1。正确的做法应该是统计分组内的OfferViewCount记录总数(对应SQL里的COUNT(*)),也就是用Count('id')或者Count('*')。

下面提供两种实用方案,根据你的需求选择:


方案一:在Offer Admin中展示浏览量(推荐)

这种方式更符合Django Admin的设计逻辑,因为浏览量是Offer的衍生属性,在Offer列表中展示并支持排序更直观。

代码实现

from django.contrib import admin
from django.db.models import Count
from .models import Offer, OfferViewCount

@admin.register(Offer)
class OfferAdmin(admin.ModelAdmin):
    # 替换成你需要展示的其他字段
    list_display = ['id', 'seller', 'view_count']
    # 默认按浏览量降序排列
    ordering = ['-view_count']
    # 可选:添加卖家筛选器
    list_filter = ['seller']

    def get_queryset(self, request):
        # 给每个Offer实例标注关联的浏览次数
        queryset = super().get_queryset(request)
        return queryset.annotate(
            view_count=Count('offerviewcount')  # 反向关联默认名称为模型名小写
        ).order_by('-view_count')

    # 自定义展示浏览次数的字段
    def view_count(self, obj):
        return obj.view_count
    view_count.short_description = '浏览次数'
    view_count.admin_order_field = 'view_count'  # 开启表头排序功能

方案二:在OfferViewCount Admin中实现分组统计

如果需要直接在OfferViewCount的Admin页面展示分组后的统计结果(每个Offer一行),可以通过重写get_queryset返回分组数据,并自定义列表显示字段。

代码实现

@admin.register(OfferViewCount)
class OfferViewCountAdmin(admin.ModelAdmin):
    list_display = ['offer_id', 'offer_seller', 'view_count']
    ordering = ['-view_count']
    # 分组结果无法进入单条记录详情,所以关闭链接
    list_display_links = None

    def get_queryset(self, request):
        queryset = super().get_queryset(request)
        # 按offer_id分组,统计记录数,同时关联Offer的卖家字段
        return queryset.values(
            'offer_id',
            'offer__seller'  # 关联Offer的seller字段用于展示
        ).annotate(
            view_count=Count('id')  # 统计分组内的记录总数,对应COUNT(*)
        ).order_by('-view_count')

    # 自定义卖家显示字段
    def offer_seller(self, obj):
        # obj是分组后的字典,直接取值
        return obj['offer__seller']
    offer_seller.short_description = '卖家'

    # 自定义Offer ID显示字段
    def offer_id(self, obj):
        return obj['offer_id']
    offer_id.short_description = 'Offer ID'

    # 自定义浏览次数显示字段
    def view_count(self, obj):
        return obj['view_count']
    view_count.short_description = '浏览次数'
    view_count.admin_order_field = 'view_count'

额外扩展:按时间范围统计

如果需要统计指定时间内的浏览量,比如近7天,可以在get_queryset中添加时间过滤:

from django.utils import timezone

def get_queryset(self, request):
    queryset = super().get_queryset(request)
    # 过滤近7天的记录
    seven_days_ago = timezone.now() - timezone.timedelta(days=7)
    queryset = queryset.filter(created_date__gte=seven_days_ago)
    
    # 后续分组逻辑不变
    return queryset.values(...)...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 21:01:22