Django annotate中处理ZeroDivisionError:除数为0时返回0
解决Django annotate中除数为0的异常问题
遇到除数为0的报错确实让人头疼,不过我们可以利用Django的Case和When表达式轻松处理这种边界情况,同时还要注意处理total_amount可能为None的潜在问题。下面是修改后的完整代码和细节说明:
修改后的代码
# 先处理total_amount可能为None的情况,默认设为0 total_amount = Invoice.objects.filter( client_account__account_UID=account_UID, created_at__range=(from_date, to_date) ).aggregate(Sum('total_amount'))['total_amount__sum'] or 0 total_billable_leads = CampaignContact.objects.filter( campaign=campaigns, billable=True, billable_item__created_at__range=(from_date, to_date) ).count() cch = CampaignContactHistory.objects.annotate( campaign_name=F('campaign__name') ).values('campaign_name' ).filter(id__in=cch_ids ).annotate( total=Count('lead_status'), scheduled=Count(Case(When(lead_status='10', then=1))), # 核心:处理除数为0的情况 total_billable=Case( # 当total_billable_leads为0时,直接返回0,跳过除法 When(Value(total_billable_leads) == 0, then=Value(0)), # 除数正常时执行原计算逻辑 default=(Value(int(total_amount)) / Value(total_billable_leads)) * Count( Case(When(campaign_contact__billable=True, then=1)) ), # 指定输出字段类型,避免数据库层面的类型冲突 output_field=models.FloatField() ), )
关键修改点说明
- 处理
total_amount的空值:用or 0把聚合查询可能返回的None转换成0,避免后续转int时触发报错。 - 用
Case/When规避除数为0:- 通过
Value()把Python层面的变量传入数据库查询表达式中 - 先判断
total_billable_leads是否为0,若是则直接返回0,跳过除法运算 - 除数正常时,执行你原本的计算逻辑
- 通过
- 指定输出字段类型:添加
output_field=models.FloatField()确保返回值类型统一,避免数据库返回结果时出现类型不匹配问题
这样修改后,既解决了除数为0的异常,也覆盖了total_amount为空的边界场景,完美适配你的需求~
内容的提问来源于stack exchange,提问作者Shubham Srivastava
相关产品推荐
相关产品推荐

