Django多对多关系更新字段报错:u'Leave_current_balance'
我来帮你梳理下这个Django假期余额更新的问题,你的代码里有几处关键错误导致了u'Leave_current_balance'相关报错,咱们一步步来修正:
问题背景
你想要在主管审批假条通过后,自动扣除用户的假期余额,但执行视图函数时出现了字段相关错误。先看你的现有代码:
模型定义
class LeaveBalance(models.Model): user=models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True,) Leave_current_balance= models.FloatField(null=True, blank=True, default=None) Year=models.CharField(max_length=100,default='') def __unicode__(self): return self.Year class NewLeave(models.Model): user=models.ForeignKey(User,default='',on_delete=models.CASCADE) # 注意:这里类名写错了,原模型是LeaveBalance,不是Leave_Balance leave_balance=models.ManyToManyField(Leave_Balance) leave=( ('annual','annual'), ('sick','sick'), ) Leave_type=models.CharField(max_length=100,choices=leave,blank=False,default='') Total_working_days=models.FloatField(null=True, blank=False) DirAuth=( ('Pending','Pending'), ('Approved','Approved'), ('Rejected','Rejected'), ) Director_Authorization_Status=models.CharField(max_length=100,choices=DirAuth,default='Pending',blank=False) Date_Authorized=models.DateField(null=True,blank=False) Authorized_by_Director=models.CharField(max_length=100,default='',blank=False) def __unicode__(self): return self.Leave_type
表单定义
class DirectorForm(forms.ModelForm): class Meta: model=NewLeave fields=('Director_Authorization_Status','Authorized_by_Director','Date_Authorized',) widgets={ 'Date_Authorized':DateInput() }
问题视图函数
def unitDirectorForm(request,id): if request.method=='POST': getstaffid=NewLeave.objects.get(id=id) form = DirectorForm(request.POST, instance=getstaffid) if form.is_valid(): getstaffid = form.save(commit=False) getstaffid.save() total_days = getstaffid.Total_working_days # 多对多字段访问错误,且OneToOne关系不需要通过多对多取 current_balance = getstaffid.user.leave_balance.Leave_current_balance diff_balance = current_balance - total_days current_balance = diff_balance # 这里完全错误,表单里根本没有这个字段,不该操作表单字段 current_balance=form.fields['Leave_current_balance'] current_balance.save() getstaffid.leave_balance.add(current_balance) return HttpResponse('You have successfuly Authorise the leave') else: # GET请求时没有传入要审批的假条实例,表单是空的 form=DirectorForm() balance_form = leavebbalanceForm() return render(request,'managerauthorisedform.html',{'form':form})
错误原因&修正方案
1. 模型类名笔误
NewLeave里的leave_balance=models.ManyToManyField(Leave_Balance)要改成LeaveBalance(原模型类名是LeaveBalance,下划线是多余的),不然Django找不到关联模型。
2. 余额实例访问错误
LeaveBalance和User是一对一关系,所以直接通过user.leavebalance(Django自动生成的反向关联名)就能获取用户的余额实例,不需要通过多对多字段。
3. 表单操作逻辑错误
你不该去操作表单的Leave_current_balance字段(这个表单里根本没有这个字段),应该直接修改LeaveBalance实例的字段然后保存。
4. 审批逻辑缺失
只有当假条被批准时才应该扣除余额,拒绝的话不需要操作余额。
修正后的视图函数
def unitDirectorForm(request,id): if request.method=='POST': # 获取要审批的假条实例 leave_request = NewLeave.objects.get(id=id) form = DirectorForm(request.POST, instance=leave_request) if form.is_valid(): # 保存审批状态 approved_leave = form.save() # 只有审批通过时才更新余额 if approved_leave.Director_Authorization_Status == 'Approved': try: # 获取用户对应的余额实例(一对一反向关联) user_balance = approved_leave.user.leavebalance except LeaveBalance.DoesNotExist: # 处理用户没有余额记录的情况 return HttpResponse('该用户暂无假期余额记录') # 扣除假期天数,处理余额为None的情况 if user_balance.Leave_current_balance is not None: user_balance.Leave_current_balance -= approved_leave.Total_working_days user_balance.save() # 如果需要把假条和余额记录关联(多对多),执行这一步 approved_leave.leave_balance.add(user_balance) return HttpResponse('你已成功审批该假条') else: # GET请求时传入要审批的假条实例,让表单显示当前状态 leave_request = NewLeave.objects.get(id=id) form = DirectorForm(instance=leave_request) return render(request,'managerauthorisedform.html',{'form':form})
额外提醒
- Python3里
__unicode__要改成__str__,不然会有兼容性问题; - 可以给
Leave_current_balance设置默认值(比如default=0.0),避免None值导致的计算错误; - 建议给一对一关系设置
related_name,比如user=models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, related_name='leave_balance'),这样访问时更清晰:user.leave_balance。
内容的提问来源于stack exchange,提问作者saum
相关产品推荐
相关产品推荐

