如何通过表单集自动将Django模型的updated_by字段填充为登录用户?
解决Django模型表单集自动填充
updated_by字段的问题 嘿,很高兴你已经上手模型表单集啦!关于自动把登录用户填充到updated_by字段的需求,我给你两个实用的方案,都是Django项目里常用的做法:
方案一:在视图层直接处理(简单直接)
这种方法适合快速实现,直接在表单集验证通过后,给每个实例手动赋值当前用户:
首先确保视图是登录保护的(避免匿名用户的情况),然后修改视图逻辑:
from django.contrib.auth.decorators import login_required from django.forms import modelformset_factory from django.shortcuts import render, redirect from .models import Inventory @login_required def inventory_formset_view(request): # 创建表单集,指定需要显示的字段(注意不要包含updated_by) InventoryFormSet = modelformset_factory(Inventory, fields=('item', 'stock', 'par')) if request.method == 'POST': formset = InventoryFormSet(request.POST) if formset.is_valid(): # 先获取未保存的实例(commit=False) instances = formset.save(commit=False) # 循环每个实例,设置updated_by为当前登录用户 for instance in instances: instance.updated_by = request.user instance.save() # 如果模型有多对多字段,记得调用save_m2m()保存关联 formset.save_m2m() return redirect('your_success_url') # 替换成你的成功跳转URL else: formset = InventoryFormSet() return render(request, 'your_template.html', {'formset': formset})
这个方法的优点是简单直观,不需要修改表单类,适合快速验证需求。
方案二:自定义表单类(更优雅安全)
把字段填充的逻辑封装在表单类里,视图会更简洁,同时能避免前端篡改字段的风险:
第一步:自定义ModelForm
from django import forms from .models import Inventory class InventoryForm(forms.ModelForm): def __init__(self, *args, **kwargs): # 从初始化参数中取出当前用户 self.current_user = kwargs.pop('user') super().__init__(*args, **kwargs) class Meta: model = Inventory fields = ('item', 'stock', 'par') # 不包含updated_by,避免前端提交篡改 def save(self, commit=True): # 重写save方法,自动填充updated_by instance = super().save(commit=False) instance.updated_by = self.current_user if commit: instance.save() return instance
第二步:创建表单集并在视图中使用
from django.contrib.auth.decorators import login_required from django.forms import modelformset_factory from django.shortcuts import render, redirect from .forms import InventoryForm @login_required def inventory_formset_view(request): # 使用自定义表单创建表单集 InventoryFormSet = modelformset_factory(Inventory, form=InventoryForm) # 传递当前用户给表单的初始化参数 form_kwargs = {'user': request.user} if request.method == 'POST': formset = InventoryFormSet(request.POST, form_kwargs=form_kwargs) if formset.is_valid(): formset.save() return redirect('your_success_url') else: formset = InventoryFormSet(form_kwargs=form_kwargs) return render(request, 'your_template.html', {'formset': formset})
这个方案的好处是把业务逻辑封装在表单类中,视图更简洁,而且因为表单里不包含updated_by字段,前端无法提交该字段的值,安全性更高。
注意事项
- 一定要用
@login_required装饰视图,确保request.user是已登录的有效用户,避免出现IntegrityError(因为updated_by是必填字段)。 - 如果是编辑已有数据,这两种方案都会自动覆盖原有的
updated_by值,符合“更新者为当前用户”的需求。
内容的提问来源于stack exchange,提问作者alejandro chapa
相关产品推荐
相关产品推荐

