Django聚合查询报错UnboundLocalError:current变量未赋值即引用
Django聚合操作触发UnboundLocalError的解决办法
使用Django对查询集执行平均值、求和等聚合操作时,根据period参数匹配对应时间段计算总和与平均值,运行时触发错误:UnboundLocalError: local variable 'current' referenced before assignment。
原代码
def metrics(request): email = request.data.get("email") period = request.data.get("period") # [0,1,2,3 : day, week, month, year] today = date.today() weekday = date.isoweekday(today) month = today.month year = today.year current_week = date.isocalendar(today).week store = Store.objects.get(account__email=email) sales = Order.objects.filter(store=store) match period: case 0: # 'Today' current = sales.filter(created__week_day=weekday) past = sales.filter(created__week_day=weekday - 1) case 1: # 'This week' current = sales.filter(created__week=current_week) past = sales.filter(created__week=current_week - 1) case 2: # 'This month' current = sales.filter(created__month=month) past = sales.filter(created__month=month - 1) case 3: # 'This year' current = sales.filter(created__year=year) past = sales.filter(created__year=year - 1) current_total = current.aggregate(Sum('products_total'))['products_total__sum'] past_total = past.aggregate(Sum('products_total'))['products_total__sum'] current_average = current.aggregate(Avg('products_total'))['products_total__avg'] past_average = past.aggregate(Avg('products_total'))['products_total__avg'] current_count = current.count() past_count = past.count()
打印的相关值
# today: 2023-05-20 # weekday: 6 # month: 5 # year: 2023 # current week: 20
Order模型定义
class Order(models.Model): products_total = models.DecimalField(max_digits=10, decimal_places=2, default=0.0) ...
尝试改用if/elif语句仍出现相同错误,不知如何修改。
问题根源
错误的核心原因是:当period参数不是0、1、2、3中的有效值时,current和past变量从未被赋值。比如period为None、其他数字或非法值时,match语句的所有case都不匹配,导致后续代码调用current.aggregate()、past.count()等方法时,变量未定义,触发UnboundLocalError。
修复方案
有两种核心修复思路,任选其一即可:
思路1:提前初始化变量
在match语句前,给current和past设置默认值(空查询集),确保无论period是否合法,变量都已定义:
# 在match语句前添加 current = sales.none() past = sales.none() match period: # 原有case逻辑保持不变
思路2:添加默认case处理非法period
给match语句添加case _:分支,处理所有不符合0-3的情况,比如直接返回错误响应:
match period: # 原有case 0-3逻辑保持不变 case _: # 拦截非法参数,返回错误 return JsonResponse({"error": "Invalid period parameter"}, status=400) # 或者设置默认查询集 # current = sales.none() # past = sales.none()
额外建议
可以在代码开头先校验period的合法性,提前拦截非法参数:
period = request.data.get("period") if period not in [0,1,2,3]: return JsonResponse({"error": "Period must be 0,1,2,3"}, status=400)
内容的提问来源于stack exchange,提问作者alkadelik
相关产品推荐
相关产品推荐

