如何在Django中保存ModelForm自定义字段的提交数据?
问题原因及解决方案
核心问题点
- 视图中读取POST参数的键名与表单定义的字段名不匹配:你表单中定义的时长字段名为
duration,但代码中用request.POST.get('dur')取值,无法获取到对应数据 - 直接从
request.POST取值没有用到表单的校验能力,存在安全风险,推荐使用表单验证后生成的cleaned_data取值 - 变量命名混淆:
form.save(commit=False)返回的是Cities模型实例,继续赋值给form变量容易引发逻辑错误
修正后的视图代码
def add_city(request): data = dict() if request.method == 'POST': form = AddCityForm(request.POST) if form.is_valid(): # 取出模型实例,不要覆盖form变量 city_obj = form.save(commit=False) # 从cleaned_data取经过校验的字段值 city_obj.city = form.cleaned_data['country'] city_obj.duration = form.cleaned_data['duration'] city_obj.something = form.cleaned_data['something'] city_obj.save() messages.success(request, '城市添加成功') data['form_is_valid'] = True else: data['form_is_valid'] = False else: form = AddCityForm() context = {'form': form} data['html_form'] = render_to_string('cites/modal_1.html', context, request=request) return JsonResponse(data)
可选优化:Form层处理逻辑
如果你不想在视图里写赋值逻辑,也可以重写ModelForm的save方法,把字段赋值逻辑放到Form中,简化视图代码,修改forms.py:
class AddCityForm(forms.ModelForm): duration = forms.ChoiceField(widget=forms.RadioSelect(attrs={ 'style': 'background-color: #FAF9F9', 'class': 'mb-3, form-check-inline'}), choices=DURATION_CHOICES) country = forms.ChoiceField(widget=forms.RadioSelect(attrs={ 'style': 'background-color: #FAF9F9', 'class': 'mb-3, form-check-inline'}), choices=CITY_CHOICE) something = forms.CharField(widget=forms.TextInput(attrs={ 'style': 'background-color: #FAF9F9', 'class': 'mb-3'})) class Meta: model = Cities exclude = ['city', 'duration', 'something'] def save(self, commit=True): instance = super().save(commit=False) instance.city = self.cleaned_data['country'] instance.duration = self.cleaned_data['duration'] instance.something = self.cleaned_data['something'] if commit: instance.save() return instance
重写save方法后,视图中不需要再手动赋值,直接调用form.save()即可完成保存:
if form.is_valid(): form.save() messages.success(request, '城市添加成功') data['form_is_valid'] = True
内容的提问来源于stack exchange,提问作者mar24n
相关产品推荐
相关产品推荐

