Django ModelForm隐藏字段无法赋值问题求助
解决Django ModelForm隐藏字段无法修改的问题
我明白你遇到的问题了——明明在视图里判断布尔字段为True时给隐藏字段赋值了,但保存后这些字段还是默认值对吧?这是因为你修改的form.cleaned_data并没有同步到表单对应的模型实例上,form.save()最终是基于form.instance来写入数据库的,所以你的修改根本没生效。
给你两种可行的解决方案,选哪种都可以:
方案一:直接修改表单实例(视图层处理)
不用再改cleaned_data了,直接操作form.instance的字段就行,因为form.save()会直接保存这个实例的状态:
修改你的views.py代码:
def rucklogs(request): if request.method == 'POST': form = RuckLogsModelForm(request.POST) if form.is_valid(): ruck_miles = form.cleaned_data.get("ruck_miles") coupon = form.cleaned_data.get("coupon") pt = form.cleaned_data.get("pt") ruck_WO_only = form.cleaned_data.get("ruck_WO_only") # 直接修改form.instance的字段 if coupon: form.instance.coupon_multiplyer = ruck_miles print("Coupon was selected") if pt: form.instance.pt_multiplyer = ruck_miles print("PT was selected.") if ruck_WO_only: form.instance.ruck_workout_multiplyer = 3 u = form.save() users = ruck_logs.objects.all() return render(request, 'datalogger/display.html', {'users': users}) else: form_class = RuckLogsModelForm return render(request, 'datalogger/rucklogs.html', { 'form': form_class, })
方案二:在表单的clean方法中处理(表单层处理,更符合Django设计)
把字段赋值的逻辑移到表单的clean方法里,这样视图代码更简洁,也符合“业务逻辑尽量放在表单/模型层”的最佳实践:
首先修改forms.py,添加clean方法:
from django.forms import ModelForm from datalogger.models import ruck_logs from django import forms class DateInput(forms.DateInput): input_type = 'date' class RuckLogsModelForm(ModelForm): class Meta: model = ruck_logs widgets = {'date_performed' : DateInput(), 'coupon_multiplyer' : forms.HiddenInput(), 'pt_multiplyer' : forms.HiddenInput(), 'ruck_workout_multiplyer' : forms.HiddenInput()} fields = ['date_performed', 'rucker_name', 'ruck_miles', 'coupon', 'pt', 'ruck_WO_only', 'coupon_multiplyer', 'pt_multiplyer', 'ruck_workout_multiplyer'] def clean(self): # 先调用父类的clean方法获取验证后的cleaned_data cleaned_data = super().clean() ruck_miles = cleaned_data.get('ruck_miles') coupon = cleaned_data.get('coupon') pt = cleaned_data.get('pt') ruck_WO_only = cleaned_data.get('ruck_WO_only') # 根据布尔字段的值修改对应的隐藏字段 if coupon: cleaned_data['coupon_multiplyer'] = ruck_miles if pt: cleaned_data['pt_multiplyer'] = ruck_miles if ruck_WO_only: cleaned_data['ruck_workout_multiplyer'] = 3 # 必须返回修改后的cleaned_data,这样表单才会把值同步到instance return cleaned_data
然后视图代码就可以简化成这样:
def rucklogs(request): if request.method == 'POST': form = RuckLogsModelForm(request.POST) if form.is_valid(): u = form.save() users = ruck_logs.objects.all() return render(request, 'datalogger/display.html', {'users': users}) else: form_class = RuckLogsModelForm return render(request, 'datalogger/rucklogs.html', { 'form': form_class, })
为什么原来的方法不生效?
当你调用form.is_valid()时,Django会完成两件事:
- 验证POST数据,生成
cleaned_data - 把
cleaned_data里的值赋值给form.instance的对应字段
但之后你修改cleaned_data,并不会自动同步回form.instance,所以form.save()还是用的之前instance里的默认值(比如0),导致隐藏字段没被修改。
两种方案都能解决这个问题,你可以根据自己的代码结构选择~
内容的提问来源于stack exchange,提问作者lonesoac0
相关产品推荐
相关产品推荐

