Django ModelForm如何实现Laravel old()式的表单旧值保留?
在Django ModelForm中实现Laravel
old('field_name') 式的表单值保留功能 在Laravel中我们通过old('field_name')显示用户此前输入的表单值,现在需要在Django的ModelForm中实现相同效果——表单验证失败时自动保留用户之前的输入内容,无需重新填写。
你当前的代码
表单代码:
class AddMenuForm(forms.ModelForm): def __init__(self,*args,**kwargs): x=super(AddMenuForm, self).__init__(*args, **kwargs) return x class Meta: model=Menu fields="__all__" widgets = { 'title': forms.TextInput(attrs={ 'class': 'form-control', 'id':'inputname', 'placeholder': "نام آیتم" }), 'url': forms.TextInput(attrs={ 'class': 'form-control', 'id': 'inputurl', 'placeholder': " mr-keshi.ir /" }),
视图代码:
class addMenu(FormView): template_name = "Menu/addMenu.html" success_url = reverse_lazy('Menu') form_class = AddMenuForm def get_context_data(self, **kwargs): if (self.kwargs['menu'] not in Menu.placeMenu): # Todo: send error message pass data = super(addMenu, self).get_context_data(**kwargs) data['places'] = Menu.placeMenu data['place'] = self.kwargs['menu'] return data def form_valid(self, form): print("form valid") menu = self.kwargs.get('menu') if (menu in Menu.placeMenu): form.save() else: pass # Todo: send error message # Todo:send success message return True def form_invalid(self, form): print("form is not valid") return super(addMenu, self).form_invalid(form)
解决方案
Django的FormView和ModelForm本身就自带表单值保留功能,只需修正几个关键问题即可:
- 修正视图的
form_valid方法
你当前的form_valid直接返回True,破坏了FormView的正常流程,导致验证成功后的重定向逻辑异常,同时可能影响验证失败时的表单状态传递。修改为调用父类的form_valid方法:
def form_valid(self, form): print("form valid") menu = self.kwargs.get('menu') if menu in Menu.placeMenu: form.save() # 可在此添加成功提示,比如使用Django messages框架 # messages.success(self.request, '菜单添加成功') else: # 添加错误提示 # messages.error(self.request, '无效的菜单位置') pass return super().form_valid(form)
- 模板中正确渲染表单字段
必须通过表单对象渲染字段,而不是手动编写原生<input>标签,这样Django才会自动填充验证失败前的用户输入值。示例模板代码:
<form method="post"> {% csrf_token %} <!-- 渲染title字段,自动保留旧值 --> {{ form.title }} <!-- 渲染url字段 --> {{ form.url }} <!-- 其他字段同理 --> <button type="submit">提交</button> </form>
你已经在表单的widgets中定义了字段的HTML属性,渲染时会自动应用这些属性,同时填充旧值。
- 简化表单的
__init__方法
当前的__init__方法仅调用父类构造,无额外逻辑,可直接删除以简化代码:
class AddMenuForm(forms.ModelForm): class Meta: model = Menu fields = "__all__" widgets = { 'title': forms.TextInput(attrs={ 'class': 'form-control', 'id':'inputname', 'placeholder': "نام آیتم" }), 'url': forms.TextInput(attrs={ 'class': 'form-control', 'id': 'inputurl', 'placeholder': " mr-keshi.ir /" }), }
关键原理
当表单验证失败时,FormView的form_invalid方法会将带有用户输入数据和错误信息的表单实例传递给模板,只要你通过{{ form.field_name }}的方式渲染字段,Django就会自动填充用户之前输入的值,实现和Laravelold('field_name')相同的效果。
内容的提问来源于stack exchange,提问作者alireza keshavarz
相关产品推荐
相关产品推荐

