在同一页面处理多个表单
我有一个账户页面,上面有三个表单。用户可以修改他们的名字、电子邮件地址和密码。
我在实现这个功能时遇到了两个困难:
1) 请求的用户信息没有及时更新(比如,有时候会滞后一个变更,或者在表单没有通过验证时才会更新)。
2) 我有三个独立的表单,但当我提交一个表单时,另一个表单却会出现验证错误信息。例如,当我提交“更改名字”的表单时,会收到密码表单中密码字段的 '这个字段是必填的'
的提示。现在我有的代码是这样的:
在表单部分:
# in forms.py
from django.contrib.auth.models import User
class ChangeNameForm(ModelForm):
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class Meta:
model = User
fields = ('first_name', 'last_name' )
class ChangeEmailForm(ModelForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ('email',)
在视图部分:
@login_required
def account(request):
name_message = password_message = email_message = ''
change_name_form = ChangeNameForm(data=request.POST or None, instance=request.user)
change_password_form = PasswordChangeForm(data=request.POST or None, user = request.user)
change_email_form = ChangeEmailForm(data=request.POST or None, instance=request.user)
if request.method == "POST":
if "change_name" in request.POST and change_name_form.is_valid():
change_name_form.save()
name_message = 'Your name has been changed.'
if "change_password" in request.POST and change_password_form.is_valid():
change_password_form.save()
password_message = 'Your password has been changed.'
if "change_email" in request.POST and change_email_form.is_valid():
...
email_message = 'Please click the link in your email to confirm changes.'
return render_to_response('userprofile/account.html',
{'change_name_form': change_name_form,
'change_email_form': change_email_form,
'change_password_form': change_password_form,
'password_message': password_message,
'name_message': name_message,
'email_message': email_message,},
context_instance=RequestContext(request))
在模板部分:
<h3>Change Name</h3>
<form method="post" action="/account/change/" name='name'> {% csrf_token %}
<h4>Change name: {{user.first_name}} {{user.last_name}}</h4>
<table>{{change_name_form.as_table}}</table>
<p>{{name_message}}</p>
<p><input type="submit" value="Save Changes" name="change_name"/></p>
</form>
<h3>Change Email</h3>
<form method="post" action="/account/change/" name='email'> {% csrf_token %}
<h4>Change email: {{user.email}}</h4>
<table>{{change_email_form.as_table}}</table>
<p>{{email_message}}</p>
<p><input type="submit" value="Save Changes" name="change_email" /></p>
</form>
<h3>Change Password</h3>
<form method="post" action="/account/change/" name='password'> {% csrf_token %}
<h4>Change password</h4>
<table>{{change_password_form.as_table}}</table>
<p>{{password_message}}</p>
<p><input type="submit" value="Save Changes" name="change_password"/></p>
</form>
我需要做些什么才能解决这两个问题:确保请求的用户信息是最新的,并且确保验证只针对当前的表单进行?另外,是否可以使用 for循环
来减少模板代码的重复?如果可以的话,考虑到有两个 name
字段,我该怎么做呢?谢谢。
2 个回答
1
针对你的第二个问题,你在处理所有三个表单时都使用了POST数据,即使那个特定的表单并没有被触发。这会导致所有三个表单都进行验证。我建议你把表单的创建放到下面的if
语句中,也就是你检查哪个submit
按钮被点击的地方。
2
我觉得martin的意思是:
@login_required
def account(request):
name_message = password_message = email_message = ''
if request.method == "POST":
change_name_form = ChangeNameForm(data=request.POST or None, instance=request.user)
change_password_form = PasswordChangeForm(data=request.POST or None, user = request.user)
change_email_form = ChangeEmailForm(data=request.POST or None, instance=request.user)
...
else:
change_name_form = ChangeNameForm(instance=request.user)
change_password_form = PasswordChangeForm(instance = request.user)
change_email_form = ChangeEmailForm(instance=request.user)
...
return render_to_response('userprofile/account.html',
{'change_name_form': change_name_form,
'change_email_form': change_email_form,
'change_password_form': change_password_form,
'password_message': password_message,
'name_message': name_message,
'email_message': email_message,},
context_instance=RequestContext(request))
如果用户向这个页面发送的是一个POST请求(也就是说,用户想要编辑他们的账户),那么你就用这个请求里的数据来创建表单。如果用户只是到达了编辑页面,但还没有进行任何编辑(也就是他们还没有提交任何表单),那么就用数据库里的数据来创建表单。