Django表单DecimalField空字符串无法转换为float该如何处理?
报错原因
当用户未填写bf字段时,浏览器提交的GET参数中会包含bf=(键存在,值为空字符串),而非不存在bf键,所以request.GET.get('bf', 0)不会触发默认值0,而是拿到空字符串'',转换float时就会触发报错。
同时你原有逻辑中的if bf is False判断永远无法触发:因为bf会被转换为float类型,数值0和布尔值False是完全不同的类型,空值场景下不会进入自动计算体脂的分支。
解决方法
推荐方案:使用Django表单内置能力
你已经定义了Form类,直接用表单自带的校验和空值处理能力即可,同时还能自动完成字段类型转换、参数合法性校验,安全性和可维护性更高,修改后视图代码如下:
def cmr(request): # 实例化表单绑定GET参数 form = CMForm(request.GET) # 校验参数合法性,校验失败可以自行添加错误跳转逻辑 if not form.is_valid(): pass cleaned = form.cleaned_data a = float(cleaned['age']) # 非必填字段未填时cleaned_data对应值为None bf = cleaned['bf'] # 未填bf时走自动计算逻辑,不需要转0 auto_calc_bf = bf is None bf = float(bf) if bf is not None else 0 s = cleaned['sex'] g = 1 if s == 'female' else 0 w = float(cleaned['weight']) h = float(cleaned['height']) act = cleaned['activeness'] u = cleaned['units'] # BooleanField未勾选时自动返回False,不需要判断'on' p = cleaned['pregnant'] lac = cleaned['lactating'] dci = 0 bmrm = 10*w+6.25*h-5*a+5 bmrf = 10*w+6.25*h-5*a-161 bmi = round(w/(h/100)**2, 1) # 改为判断是否需要自动计算体脂 if auto_calc_bf: bf = round(-44.988 + (0.503 * a) + (10.689 * g) + (3.172 * bmi) - (0.026 * bmi**2) + (0.181 * bmi * g) - (0.02 * bmi * a) - (0.005 * bmi**2 * g) + (0.00021 * bmi**2 * a), 1) tbf = w*(bf/100) ffm = w*(1-(bf/100)) ffmi = ffm/(h/100)**2 nffmi = ffmi+6.1*(1.8-(h/100)) if p: dci = 300 if lac: dci = dci+500 if s == 'male': bmr = dci+bmrm dcis = bmrm*1.2 dcil = bmrm*1.375 dcim = bmrm*1.55 dciv = bmrm*1.725 dcie = bmrm*1.9 else: bmr = dci+bmrf dcis = dci+bmrf*1.2 dcil = dci+bmrf*1.375 dcim = dci+bmrf*1.55 dciv = dci+bmrf*1.725 dcie = dci+bmrf*1.9 context = {'dci': round(int(dci)), 'p': p, 'lac': lac, 'bmr': int(bmr), 'dcis': int(dcis), 'dcil': int(dcil), 'dcim': int(dcim), 'dciv': int(dciv), 'dcie': int(dcie), 'act': act, 'bmi': bmi, 'bf': bf, 'tbf': round(tbf, 1), 'ffm': round(ffm, 1), 'ffmi': round(ffmi, 1), 'nffmi': round(nffmi, 1), } return render(request, "calorie_maintenance_result.html", context)
快速修复方案:仅修改bf取值逻辑
如果不想改动现有整体逻辑,只需要把bf取值的代码改为如下即可:
bf_raw = request.GET.get('bf', '').strip() bf = float(bf_raw) if bf_raw else 0 # 同时把原来的if bf is False判断改为if bf == 0,保证自动计算逻辑可以触发
内容的提问来源于stack exchange,提问作者Ángel Guzmán
相关产品推荐
相关产品推荐

