如何在Django中管理员批准前临时保存数据库更新请求?
这是个很典型的用户内容审核场景,我来给你分享几个更灵活的实现思路,应该能解决你之前提到的痛点:
方案1:通用审核请求模型(首推)
这个思路能完美解决多模型场景的复用问题,不用给每个需要审核的模型单独建表,而且不会污染原模型的结构。核心是利用Django的ContentType通用关联来记录任意模型的修改请求,再用JSON字段存储具体的修改内容。
模型定义
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.auth.models import User class PendingChange(models.Model): # 关联被修改的目标实例(支持任意模型) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') # 存储具体的修改内容:键是字段名,值是修改后的新值 changes = models.JSONField() # 提交信息 submitted_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) submitted_at = models.DateTimeField(auto_now_add=True) # 审核状态 STATUS_CHOICES = [ ('pending', '待审核'), ('approved', '已通过'), ('rejected', '已拒绝'), ] status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending') # 审核信息 reviewed_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='reviewed_changes') reviewed_at = models.DateTimeField(null=True, blank=True) def __str__(self): return f"修改请求:{self.content_object} - {self.submitted_by}"
工作流程
用户提交修改:
用户在表单里填写完修改内容后,后端不直接更新MyModel实例,而是:- 获取原实例的当前数据
- 对比表单提交的数据,提取出有变化的字段和新值(比如只记录
description的修改) - 创建一个
PendingChange实例,关联到目标MyModel,把变化内容存入changes字段
示例代码(视图里的逻辑):
def submit_edit(request, model_id): instance = MyModel.objects.get(id=model_id) form = MyModelEditForm(request.POST, instance=instance) if form.is_valid(): # 提取有变化的字段 changes = {} for field in form.changed_data: changes[field] = form.cleaned_data[field] # 创建审核请求 PendingChange.objects.create( content_object=instance, changes=changes, submitted_by=request.user if request.user.is_authenticated else None ) # 返回成功提示 return HttpResponseRedirect('/success/')管理员审核:
- 在管理员后台(可以用Django Admin自定义页面,或者自己写视图)列出所有
status='pending'的修改请求 - 每个请求可以展示原实例的当前值和修改后的新值(方便对比)
- 点击「批准」时,遍历
changes字段的键值对,更新原实例对应的字段,然后把PendingChange的status设为approved,记录审核者和时间 - 点击「拒绝」时,直接修改
status为rejected即可
- 在管理员后台(可以用Django Admin自定义页面,或者自己写视图)列出所有
优势
- 完全通用:支持所有需要审核的模型,不用重复建表
- 数据干净:原模型不需要添加额外字段,所有修改请求都集中在一个表管理
- 记录清晰:能准确看到每个修改请求的目标实例、修改内容、提交人、审核状态
补充优化建议
- 提交修改时,只记录有变化的字段,避免存储冗余数据
- 管理员审核页面可以做字段对比展示(比如用diff效果),更直观
- 可以给
PendingChange加一个note字段,让用户填写修改原因,帮助管理员判断 - 审核通过/拒绝后,可以给提交用户发送通知(比如站内信或邮件)
对比你之前的方案
- 比「专用EditToMyModel模型」更灵活,不用为每个模型单独建表,维护成本更低
- 比「给原模型加额外字段」更清晰,不会把审核状态和原业务数据混在一起,原模型的职责更单一
内容的提问来源于stack exchange,提问作者Siolan
相关产品推荐
相关产品推荐

