Django表单int()转空字符串触发ValueError的解决方法
Django表单old_car字段int()转换报错解决方案
问题现象
Django表单开发过程中做字段值追加处理时,old_car字段触发如下报错:
ValueError: invalid literal for int() with base 10: ''
当前业务逻辑要求new_car、old_car字段的字符串类型返回值必须转换为整数,供后续条件判断逻辑使用;直接移除int()强制转换只能临时规避报错,不符合业务规则要求。
原问题代码
car = cleaned_data.get("user", ['AUTO']) if car[0] == 'AUTO': records = [] for i in range(count): new_car = int(self.data.get(f'cardefination_set-{i}-new_car', [])) old_car =int(self.data.get(f'cardefination_set-{i}-old_car', [])) records.append((new_car, old_car)) records = sorted(records, key=lambda record: record[1])
报错根因
- 当表单对应字段用户未填写时,从
self.data取到的原始值是空字符串'',int()方法无法将空字符串转为整数,直接触发值错误 - 原代码给字典
get()方法设置的默认值是空列表[],和字段实际返回的字符串类型完全不匹配,一旦对应字段键不存在,把列表传入int()同样会触发类型错误 - 直接读取未经过Django表单校验清洗的
self.data原始数据本身不符合开发规范,原始数据没有做格式校验、类型转换,很容易出现各类值异常问题
合规修复方案
快速兼容修复
针对现有代码逻辑做兼容处理,先对取到的值做空值判断,设置类型匹配的默认值,再做整数转换,避免非法值传入int():
car = cleaned_data.get("user", ['AUTO']) if car[0] == 'AUTO': records = [] for i in range(count): # 取字符串类型字段值,默认值设为'0',同时去除首尾空白字符 new_car_str = self.data.get(f'cardefination_set-{i}-new_car', '0').strip() old_car_str = self.data.get(f'cardefination_set-{i}-old_car', '0').strip() # 空值场景使用默认值0(可根据业务需求调整默认值),再做类型转换 new_car = int(new_car_str) if new_car_str else 0 old_car = int(old_car_str) if old_car_str else 0 records.append((new_car, old_car)) records = sorted(records, key=lambda record: record[1])
如果业务要求字段不能为空,不要给空值设默认值,直接在空值判断分支抛出表单校验错误,引导用户补全字段即可。
规范优化方案(推荐)
如果是Django表单集(formset)场景,不要手动拼接字段名从原始请求数据里取值,直接遍历表单集校验后的数据,Django会自动完成字段格式校验、类型转换,从根源避免空值、类型不匹配问题:
car = cleaned_data.get("user", ['AUTO']) if car[0] == 'AUTO': records = [] # 遍历关联表单集的校验后数据 for form in self.cardefination_set.forms: if form.is_valid(): new_car = form.cleaned_data.get('new_car', 0) old_car = form.cleaned_data.get('old_car', 0) records.append((new_car, old_car)) records = sorted(records, key=lambda record: record[1])
内容的提问来源于stack exchange,提问作者Gomepz
相关产品推荐
相关产品推荐

