Django:在通用UpdateView中修改用户输入前获取初始值
解决Django ModelForm累加更新时获取实例初始值的问题
嘿,我完全懂你遇到的困扰——当用户提交新的水果数量后,self.instance里的字段已经被表单的新值覆盖了,所以你打印出来的是用户输入的X,而不是数据库里原本的A。别着急,这有个很直接的解决办法!
问题根源
当Django的ModelForm初始化时,如果传入了instance参数,表单会把实例的当前值加载到字段里,但一旦用户提交新值,self.instance的字段就会被新的cleaned_data覆盖,所以在save方法里直接访问它,拿到的已经不是数据库里的原始数值了。
方案一:初始化时保存初始值
我们可以在表单的__init__方法里,把实例的原始水果数量存到一个自定义属性里,这样在save阶段就能调用这些初始值来做累加计算。
修改后的BasketForm代码如下:
class BasketForm(ModelForm): class Meta: model = Basket fields = ['apples', 'oranges', 'bananas'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 仅当编辑现有篮子实例时,保存原始数值 if self.instance.pk: self.initial_fruit_counts = { 'apples': self.instance.apples, 'oranges': self.instance.oranges, 'bananas': self.instance.bananas, } self.helper = FormHelper() self.helper.add_input(Submit('submit', 'UPDATE')) def save(self, commit=True): # 获取用户输入的增量值 add_apples = self.cleaned_data.get('apples') add_oranges = self.cleaned_data.get('oranges') add_bananas = self.cleaned_data.get('bananas') # 用原始值+增量更新实例 if hasattr(self, 'initial_fruit_counts'): self.instance.apples = self.initial_fruit_counts['apples'] + add_apples self.instance.oranges = self.initial_fruit_counts['oranges'] + add_oranges self.instance.bananas = self.initial_fruit_counts['bananas'] + add_bananas # 调用父类方法完成保存 instance = super().save(commit=commit) return instance
方案二:直接从数据库拉取原始实例
如果你不想在初始化阶段保存值,也可以在save方法里通过实例的pk重新从数据库获取原始数据(一定要在修改当前实例之前做这件事):
def save(self, commit=True): # 从数据库获取未被修改的原始实例 original_basket = Basket.objects.get(pk=self.instance.pk) # 计算新数值:原始值 + 用户输入的增量 self.instance.apples = original_basket.apples + self.cleaned_data.get('apples') self.instance.oranges = original_basket.oranges + self.cleaned_data.get('oranges') self.instance.bananas = original_basket.bananas + self.cleaned_data.get('bananas') return super().save(commit=commit)
小提示
- 记得加判断:只有当
self.instance.pk存在(也就是编辑现有篮子)时才执行累加逻辑,如果是新增篮子,直接保存用户输入的值即可。 - 因为用的是
DecimalField,加法操作不会有精度问题,Django已经帮我们处理好了这类细节。
这样修改后,就能完美实现“用户输入的数量是累加而非直接覆盖”的需求啦!
内容的提问来源于stack exchange,提问作者Russel B
相关产品推荐
相关产品推荐

