Django项目中如何实现表单更新需指定用户审批后展示
核心实现方案
当前代码的核心缺陷是Lead提交更新时直接通过form.save()覆盖正式生效的DoaTable数据,没有审批状态隔离,导致未审核内容直接对外生效。可以按照以下分层逻辑改造,全程保持系统轻量:
模型层改造
在现有模型基础上新增审批状态字段,拆分“正式生效数据”和“待审批草稿”两个数据层级:
# approvals/models.py class DoaTable(models.Model): LIMITS = ( ('Low Risk', 'Low Risk'), (...), ('Strict Credit Check', 'Strict Credit Check'), ('No Credit Check', 'No Credit Check'), ) RANKS = ( ('Analyst', 'Analyst'), ('Senior Analyst', 'Senior Analyst'), ('Lead', 'Lead'), ('Manager', 'Manager'), ('...Officer'), ) rank = models.CharField(max_length=200, choices=RANKS) risk = models.CharField(max_length=200, choices=LIMITS) limit = models.FloatField() comp_name = models.ForeignKey(CompanyProfile, on_delete=models.CASCADE, null=True) # 新增审批相关字段 is_approved = models.BooleanField(default=True, verbose_name="是否为已审批正式数据") submitted_by = models.ForeignKey( UserProfile, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="草稿提交人" ) class Meta: # 约束:同公司、同职级、同风险维度仅能存在1条已审批的正式数据 unique_together = [("comp_name", "rank", "risk", "is_approved")]
视图层逻辑改造
Lead提交更新逻辑
去掉原有直接覆盖正式数据的保存逻辑,Lead提交内容时仅生成待审批草稿,不直接修改正式数据:
# approvals/views.py from django.contrib.auth.decorators import login_required from django.http import HttpResponseForbidden @login_required def update_limit(request, id): # 身份校验:仅Lead可提交更新申请 if request.user.rank != "Lead": return HttpResponseForbidden("无提交权限") # 获取正式生效的额度记录,直接过滤掉草稿数据 limiting = get_object_or_404(DoaTable, id=id, is_approved=True) form = UpdateDoaTableForm(request.POST or None) if form.is_valid(): # 不直接绑定原实例保存,创建全新草稿 draft = form.save(commit=False) # 继承正式记录的关联属性,仅使用Lead修改的limit值 draft.rank = limiting.rank draft.risk = limiting.risk draft.comp_name = limiting.comp_name draft.is_approved = False draft.submitted_by = request.user draft.save() return redirect('approvals:my_draft_list') context = { 'form': form, 'limiting_item': limiting } return render(request, 'limitUpdate.html', context)
注意:禁止在Lead提交时使用关联了正式DoaTable实例的表单保存逻辑,否则会直接覆盖正式生效的数据。
Manager审批逻辑
新增审批视图,仅向Manager展示待审批草稿列表,提供通过/驳回两个操作分支:
@login_required def process_draft(request, draft_id): # 身份校验:仅Manager可执行审批操作 if request.user.rank != "Manager": return HttpResponseForbidden("无审批权限") draft = get_object_or_404(DoaTable, id=draft_id, is_approved=False) if request.method == "POST": action = request.POST.get("action") if action == "approve": # 删除同维度的旧正式数据 DoaTable.objects.filter( comp_name=draft.comp_name, rank=draft.rank, risk=draft.risk, is_approved=True ).delete() # 将当前草稿转为正式生效数据 draft.is_approved = True draft.save() elif action == "reject": # 驳回则直接删除草稿 draft.delete() return redirect("approvals:draft_approval_list") return render(request, "draft_approval.html", {"draft": draft})
对外展示规则
所有面向普通用户、前端页面的正式额度查询,必须在ORM层加is_approved=True的过滤条件,从根源上避免草稿数据被泄露展示:
- 统一查询写法示例:
DoaTable.objects.filter(is_approved=True, comp_name=当前关联公司) - 禁止在全表查询后再做内存过滤,避免漏判草稿数据
轻量优化:Lead提交新草稿时,可自动删除该Lead针对同维度正式额度提交的旧未审批草稿,避免审批列表出现重复申请
内容的提问来源于stack exchange,提问作者user14887093
相关产品推荐
相关产品推荐

