在同一页面处理多个表单

0 投票
2 回答
1481 浏览
提问于 2025-04-16 19:07

我有一个账户页面,上面有三个表单。用户可以修改他们的名字、电子邮件地址和密码。

我在实现这个功能时遇到了两个困难:

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请求(也就是说,用户想要编辑他们的账户),那么你就用这个请求里的数据来创建表单。如果用户只是到达了编辑页面,但还没有进行任何编辑(也就是他们还没有提交任何表单),那么就用数据库里的数据来创建表单。

撰写回答