【问题标题】:Processing multiple forms on same page在同一页面上处理多个表单
【发布时间】:2011-06-07 19:02:03
【问题描述】:

我有一个帐户页面,其中包含三个表单。用户可以更改他的姓名、电子邮件地址和密码。

尝试这样做有两个困难:

1) request.user 信息没有相应更新(例如,它会滞后一次更改,或者如果表单未通过验证,它将更新)

2) 我有三个单独的表单,但是,当我提交一个表单时,我会从另一个表单收到验证消息。例如,如果我提交“更改名称”表单,我会从密码表单的密码字段中获得'This field is required。这是我目前拥有的——

形式:

# 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>

我需要做些什么来解决确保 request.user 信息是最新的和确保仅对当前表单运行验证这两个问题?另外,是否可以运行for loop 来减少模板代码中的冗余?如果是这样,考虑到两个 name 字段,我将如何做到这一点?谢谢。

【问题讨论】:

    标签: python django django-forms django-views


    【解决方案1】:

    我认为马丁的意思是:

    @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(即用户正在尝试编辑他们的帐户),则您使用请求 POST 属性来实例化表单。如果他们刚刚到达编辑页面,但还没有执行编辑(即他们还没有发布任何表单),那么只需使用数据库中的数据实例化表单

    【讨论】:

    • 啊我明白了,谢谢你的解释。你知道为什么 request.user 信息没有保持最新吗?
    【解决方案2】:

    要回答您的第二个问题,您将使用 POSTd 数据实例化所有 3 个表单,即使该特定表单不是被触发的。这将触发所有 3 个表单的验证。我会将表单实例化向下移动到下面的if 语句中,您可以在其中检查是否存在适当的submit 按钮。

    【讨论】:

    • 我不太明白。您能否发布您的意思的代码部分?
    • 类似这样的东西:if request.POST.has_key('change_password'): change_password_form = PasswordChangeForm(data=request.POST, user=request.user) elif request.POST.has_key('change_name'): change_name_form = ChangeNameForm(data=request.POST, user=request.user) ... 呃,抱歉格式化。不确定如何正确格式化 cmets。
    猜你喜欢
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    相关资源
    最近更新 更多