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

如何通过Django ORM查询计算每个用户的累计登录时长及平均登录时长

计算用户累计/平均登录时长的ORM实现方案

前置说明

你当前的模型存在逻辑缺陷:AllLogin和AllLogout两张表没有关联字段,无法直接匹配某一次登录对应的登出记录。以下方案基于同一个用户同一天的登录、登出记录视为一次登录会话的逻辑实现,如果需要更精准的会话配对,建议先给AllLogout表新增login_record外键关联AllLogin表,每次用户登出时绑定对应登录记录。

具体代码实现

依赖导入

需要提前导入Django ORM相关的工具类:

from django.db.models import F, Sum, Avg, ExpressionWrapper, DurationField
from django.db.models.functions import Combine
from rest_framework import status

视图函数代码

class ListUsers(generics.GenericAPIView):
    def get(self,request):
        # 1. 关联登录登出记录,拼接完整datetime并计算单次会话时长
        login_logout_pairs = AllLogin.objects.annotate(
            # 把分开存储的登录日期、时间拼接为完整datetime
            login_datetime=Combine('login_date', 'login_time'),
            # 匹配同用户同日期的登出记录,默认取第一条,可按需调整排序
            logout_datetime=AllLogout.objects.filter(
                user=F('user'),
                logout_date=F('login_date')
            ).annotate(
                full_logout=Combine('logout_date', 'logout_time')
            ).order_by('logout_time').values('full_logout')[:1]
        ).annotate(
            # 计算单次登录的时长
            session_duration=ExpressionWrapper(
                F('logout_datetime') - F('login_datetime'),
                output_field=DurationField()
            )
        )

        # 2. 按用户分组,统计累计登录时长和平均登录时长
        user_stats = login_logout_pairs.values('user', 'user__username').annotate(
            total_duration=Sum('session_duration'),
            avg_duration=Avg('session_duration')
        )

        # 3. 格式化返回结果
        result = []
        for stat in user_stats:
            result.append({
                "用户ID": stat['user'],
                "用户名": stat['user__username'],
                "累计登录时长": str(stat['total_duration']),
                "平均登录时长": str(stat['avg_duration'])
            })
        
        return Response(result, status=status.HTTP_200_OK)

注意事项

  • 如果业务允许用户同一天多次登录登出,修改模型加关联外键后,只需要把上述的登出记录匹配逻辑替换为外键关联即可,避免多对多匹配错误
  • DurationField返回的结果是Python的timedelta类型,转字符串后默认格式为X天 X:X:X,你可以按需换算为秒、分钟等数值单位返回
  • 可以根据需求加时间范围过滤,比如只统计近一个月的记录,在AllLogin的查询后加filter(login_date__gte=xxx)即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:09:01