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

Django 1.11 Admin实现事件统计及按指定时间排序方案

Django 1.11 Admin 实现需求方案

一、模型优化(可选)

原模型中event字段为TextField,且有固定可选值A/B/C,推荐改为带选项的CharField,避免非法输入:

class Random(models.Model):
    EVENT_CHOICES = (
        ('A', '事件A'),
        ('B', '事件B'),
        ('C', '事件C'),
    )
    person = models.TextField(blank=True, null=True)
    event = models.CharField(max_length=1, choices=EVENT_CHOICES, blank=True, null=True)
    event_date = models.DateTimeField(blank=True, null=True)

二、Admin核心实现

在admin.py中通过聚合查询和子查询实现需求,具体代码如下:

from django.contrib import admin
from django.db.models import Count, Case, When, Subquery, OuterRef, DateTimeField
from .models import Random

class RandomAdmin(admin.ModelAdmin):
    # 配置列表显示字段
    list_display = (
        'person',
        'event_count_A',
        'event_count_B',
        'event_count_C',
        'latest_A_event',
    )

    def get_queryset(self, request):
        # 子查询:获取每个人员最近一次事件A的时间
        latest_a_subquery = Random.objects.filter(
            person=OuterRef('person'),
            event='A'
        ).order_by('-event_date').values('event_date')[:1]

        # 主查询:筛选参与过A事件的人员,按人员分组统计各事件次数
        qs = Random.objects.filter(event='A').values('person').annotate(
            event_count_A=Count(Case(When(event='A', then=1))),
            event_count_B=Count(Case(When(event='B', then=1))),
            event_count_C=Count(Case(When(event='C', then=1))),
            latest_A_event=Subquery(latest_a_subquery, output_field=DateTimeField())
        ).distinct().order_by('-latest_A_event')
        
        return qs

    # 定义各统计字段的显示逻辑
    def event_count_A(self, obj):
        return obj['event_count_A']
    event_count_A.short_description = 'event-count-A'

    def event_count_B(self, obj):
        return obj['event_count_B']
    event_count_B.short_description = 'event-count-B'

    def event_count_C(self, obj):
        return obj['event_count_C']
    event_count_C.short_description = 'event-count-C'

    # 格式化最近A事件的日期显示
    def latest_A_event(self, obj):
        return obj['latest_A_event'].strftime('%d %b %Y') if obj['latest_A_event'] else '-'
    latest_A_event.short_description = 'latest_A_event'

admin.site.register(Random, RandomAdmin)

代码说明

  1. 筛选与分组:通过filter(event='A')筛选参与过A事件的记录,再用values('person').distinct()得到唯一人员列表,确保按人员分组统计。
  2. 事件次数统计:使用annotate结合Case/When和Count函数,分别统计每个人员参与A、B、C事件的次数。
  3. 最近A事件时间:通过Subquery子查询获取每个人员最近一次A事件的时间,作为排序依据。
  4. 排序与显示:按latest_A_event倒序排列,自定义显示方法格式化日期并设置列名。

内容的提问来源于stack exchange,提问作者Apple-and-Oranges

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 20:40:50