不使用Django Forms多HTML表单上传单图出现NoReverseMatch错误如何解决
问题根源
1. 直接报错(NoReverseMatch)
你的icard_edit路由要求必须传入pk参数,但你在异常捕获块中执行redirect('icard_edit')时没有传递pk,导致路由反向解析失败。
2. 触发异常的原因(MultiValueDictKeyError)
你当前的逻辑强制要求每次提交表单时必须同时上传logo和背景两张图片,只要有一个文件输入框没有选择文件,request.FILES中就不存在对应的key,直接用request.FILES['myfile']取值就会抛出键错误,进入异常捕获逻辑。
修复方案
第一步:修复重定向参数问题
将views.py中except块的重定向代码修改为传入pk参数:
except: return redirect('icard_edit', pk=pk)
第二步:优化图片上传逻辑,支持单图可选修改
不要强制要求每次提交都上传所有图片,存在上传文件时才执行替换逻辑,否则保留原有数据:
def icard_edit(request, pk): icard = Icard.objects.get(pk=pk) if request.method == 'POST': try: # 从POST中获取普通表单字段 name = request.POST.get('name') category = request.POST.get('category') feature_one = request.POST.get('feature_one') # 用get方法取文件,不存在则为None myfile = request.FILES.get('myfile') bg_myfile = request.FILES.get('bg_myfile') fs = FileSystemStorage() # 处理logo上传逻辑 if myfile: # 校验文件类型 if not str(myfile.content_type).startswith("image"): error = "Logo文件格式不支持" return render(request, 'back/error.html', {'error': error}) # 校验文件大小 if myfile.size >= 5000000: error = "Logo文件大小不能超过5MB" return render(request, 'back/error.html', {'error': error}) # 保存新文件,删除旧文件 filename = fs.save(myfile.name, myfile) url = fs.url(filename) fs.delete(icard.logo) icard.logo = filename icard.logo_url = url # 处理背景图上传逻辑 if bg_myfile: if not str(bg_myfile.content_type).startswith("image"): error = "背景图文件格式不支持" return render(request, 'back/error.html', {'error': error}) if bg_myfile.size >= 5000000: error = "背景图文件大小不能超过5MB" return render(request, 'back/error.html', {'error': error}) bg_filename = fs.save(bg_myfile.name, bg_myfile) bg_url = fs.url(bg_filename) fs.delete(icard.bg_image) icard.bg_image = bg_filename icard.bg_url = bg_url # 更新其他字段并保存 icard.name = name icard.category = category icard.feature_one = feature_one icard.save() print("func: Icard Data Edit Saved") return redirect('icard_list') except Exception as e: # 开发阶段可打印异常方便排查,生产环境可删除 print(e) return redirect('icard_edit', pk=pk) return render(request, 'back/icards/icard_edit.html', {'pk': pk, 'icard': icard})
其他优化建议
- 原代码中判断条件用的
&是位运算符,逻辑判断应该使用and - 可以在前端文件输入框添加
accept="image/*"属性,提前限制用户可选的文件类型,减少不必要的校验失败
内容的提问来源于stack exchange,提问作者Cory Billeaud
相关产品推荐
相关产品推荐

