You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:25:39