Django报local variable 'med' referenced before assignment错误
问题根因
触发UnboundLocalError的核心原因是变量作用域逻辑漏洞:
当访问的患者还未创建对应医疗信息记录时,try块中med = medInfo.objects.get(pat_ID=patid)的查询语句会抛出DoesNotExist异常,代码直接进入except分支。但原代码的except分支仅处理了GET请求的页面返回,既没有给med变量赋值,也没有处理该场景下的POST请求逻辑。当用户在新建医疗记录的页面提交POST请求时,代码走到POST处理分支直接引用从未被赋值的med变量,就会触发「局部变量赋值前被引用」的报错。
除此之外原代码还存在多处逻辑缺陷,导致新建医疗记录的流程完全无法走通,只能在已有记录的更新场景下(也就是Django Admin提前创建好记录的场景)正常运行。
修复后完整代码
from django.shortcuts import render, redirect, get_object_or_404 from django.core.exceptions import ObjectDoesNotExist @login_required def medinfoupdate(request, patid): # 获取对应患者基础信息,不存在直接返回404 patprofileedit = get_object_or_404(patientprofile, id=patid) med = None # 仅捕获医疗记录不存在的异常,不使用裸except吞掉所有错误 try: med = medInfo.objects.get(pat_ID=patid) except ObjectDoesNotExist: pass if request.method == 'POST': # 有现存记录就绑定实例做更新,无记录就传参生成空表单做新建 form = medInfo_form(request.POST, instance=med) if form.is_valid(): # 先不提交数据库,新建场景下补全关联的患者外键再保存 med_record = form.save(commit=False) if not med: med_record.pat_ID = patprofileedit med_record.save() # 注意redirect要传入路由命名的字符串,不要直接写未定义变量 return redirect('patientlist') else: # 表单校验失败时保留用户输入,返回错误提示 return render(request, 'pmp/medinfo.html', { 'form': form, 'patprofileedit': patprofileedit, 'error': '输入数据有误,请检查后重新提交' }) else: # GET请求统一返回表单:有记录绑定实例数据,无记录返回空表单 form = medInfo_form(instance=med) return render(request, 'pmp/medinfo.html', { 'med': med, 'form': form, 'patprofileedit': patprofileedit })
核心修复点说明
- 提前初始化
med变量为None,从根源上避免变量未赋值就被引用的作用域问题 - 替换裸
except为明确捕获ObjectDoesNotExist异常,避免吞掉数据库连接错误、代码语法错误等无关异常,降低问题排查难度 - 统一GET/POST请求的处理逻辑,不再把请求处理拆分在try/except块中,同时覆盖「更新已有医疗记录」和「新建医疗记录」两个场景
- 补全新建场景的缺失逻辑:GET请求返回空表单供用户填写,POST提交保存时自动给新记录绑定关联的患者外键,避免外键缺失报错
- 修正路由跳转的写法错误,redirect传入路由命名字符串而不是未定义的变量
- 替换原来仅捕获ValueError的简陋错误处理,增加Django表单自带的
is_valid()校验,校验不通过时保留用户已输入内容,减少重复输入成本
内容的提问来源于stack exchange,提问作者Saravanan Ragavan
相关产品推荐
相关产品推荐

