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

在Django中如何计算关联表datetime字段差值的平均值?

报错原因&解决方案

你遇到的报错和计算逻辑错误来自三个核心问题,按顺序修改即可:

1. 反向关联名称不匹配(报错的直接原因)

你在Orders模型的item外键字段设置了related_name='gig',意味着Gigs实例反向查询关联订单的字段名是gig,不是你代码里写的orders,所以Django找不到orders字段才会报对应错误。

如果想要更符合语义的命名,建议先修改buyer应用下Models.py的Orders字段:

# 将related_name从gig改成orders,后续写代码更不容易混淆
item = models.ForeignKey(Gigs,default=None, on_delete=models.CASCADE,related_name='orders')

修改后执行makemigrations和migrate更新配置即可。


2. 时间差计算逻辑修正

不能直接对字段名字符串做减法,需要用Django的F表达式取字段值,配合ExpressionWrapper指定时间差输出类型,同时可以直接在查询层做注解避免N+1性能问题。

首先修改Views.py,导入依赖并改写查询集:

from django.db.models import F, Avg, ExpressionWrapper, DurationField

class RetrieveGigsAPI(GenericAPIView, RetrieveModelMixin):
    def get_queryset(self):
        return Gigs.objects.annotate(
            # 直接在查询时注解计算好平均耗时,避免每个实例单独查库
            _average_completionTime=Avg(
                ExpressionWrapper(
                    F('orders__order_completed_time') - F('orders__order_start_time'),
                    output_field=DurationField()
                ),
                # 可选:添加过滤条件,只统计已完成的订单
                filter=Q(orders__status='completed')
            )
        )
    serializer_class = GigsSerializerWithAvgTime
    permission_classes = (AllowAny,)

    def get(self, request , *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

3. 修正Gigs模型的属性逻辑

修改seller应用下Models.py的average_completionTime属性,直接复用查询层注解的结果,不需要重复计算:

@property
def average_completionTime(self):
    # 优先取查询时注解好的结果,没有注解的情况再兜底计算
    if hasattr(self, '_average_completionTime'):
        # 可选:如果需要返回分钟/秒数,在这里做转换:return self._average_completionTime.total_seconds() / 60
        return self._average_completionTime
    # 兜底计算逻辑
    from django.db.models import F, Avg, ExpressionWrapper, DurationField, Q
    return self.orders.filter(status='completed').aggregate(
        avg_time=Avg(
            ExpressionWrapper(
                F('order_completed_time') - F('order_start_time'),
                output_field=DurationField()
            )
        )
    )['avg_time']

可选优化

如果需要把时间差格式化成易读的字符串,可以在序列化器的get_average_completionTime方法里做格式转换,不需要修改原有逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 06:57:05