django中有多个表单和一个提交。未提交的表单上的错误

时间:2017-03-15 02:05:20

标签: django django-forms

我能够成功更新三种表格中的任何一种。但是,我的问题是,如果更改密码表单为空,则会抛出错误(如密码太短,当前密码不正确等),不像其他表格,如果我保持不变,我不会收到错误。我该如何处理修复?我尝试设置request.POST or None无效,但我的想法已经不多了。我也没有使用{{ form.as_p }},而是逐场进行。这可能是一个问题吗?

表格

forms.py

from django.contrib.auth.forms import PasswordChangeForm

class UserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'email')
        widgets = {
            'first_name': forms.TextInput(attrs={
                'class': 'lnd-user__input',
                'id': 'first_name',
                'placeholder': 'First Name'}),

            'last_name': forms.TextInput(attrs={
                'class': 'lnd-user__input',
                'id': 'last_name',
                'placeholder': 'Last Name'}),

            'email': forms.TextInput(attrs={
                'class': 'lnd-user__input',
                'id': 'email',
                'placeholder': 'Email'}),

        }


class UserProfileForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ('mobile',)

        widgets = {
            'mobile': forms.TextInput(attrs={
                'class': 'lnd-user__input',
                'id': 'mobile',
                'placeholder': 'Phone Number'})
        }


class MyPasswordChangeForm(PasswordChangeForm):

    old_password = forms.CharField(
        label=("Old password"),
        required=False,
        strip=False,
        widget=forms.PasswordInput(attrs={
                'class': 'lnd-user__input',
                'id': 'new_password2',
                'type': 'password',
                'placeholder': 'Old Password'}),
    )

    new_password1 = forms.CharField(
        label=("New password"),
        required=False,
        widget=forms.PasswordInput(attrs={
                'class': 'lnd-user__input',
                'id': 'new_password2',
                'type': 'password',
                'placeholder': 'Enter new Password'}),
        strip=False,
        help_text=password_validation.password_validators_help_text_html(),
    )
    new_password2 = forms.CharField(
        label=("New password confirmation"),
        required=False,
        strip=False,
        widget=forms.PasswordInput(attrs={
                'class': 'lnd-user__input',
                'id': 'new_password2',
                'type': 'password',
                'placeholder': 'Repeat new Password'}),
    )

views.py

@login_required(login_url='/accounts/login/')
def user_settings(request):
    if request.method == 'GET':
        user = User.objects.get(id=request.user.id)
        user_profile = UserProfile.objects.get(user=user)
        user_form = UserForm(instance=user)
        user_profile_form = UserProfileForm(instance=user_profile)
        password_change_form = MyPasswordChangeForm(user)
        context = {
            'uform': user_form,
            'pform': user_profile_form,
            'pwdform': password_change_form,
            'user': user}

        return render(request, 'accounts/user_settings.html', context)

    if request.method == 'POST':
        user = User.objects.get(id=request.user.id)
        user_profile = UserProfile.objects.get(user=user)

        user_form = UserForm(request.POST or None, instance=user)
        user_profile_form = UserProfileForm(request.POST or None, instance=user_profile)
        password_change_form = MyPasswordChangeForm(user, request.POST or None, use_required_attribute=False)
        print password_change_form.is_valid(), password_change_form.error_messages
        if request.POST:
            if user_form.is_valid() is True and user_profile_form.is_valid() is True:
                user = user_form.save(commit=False)
                user.save()
                profile = user_profile_form.save(commit=False)
                user = User.objects.get(id=request.user.id)
                profile.user = user
                profile.save()

            if password_change_form.is_valid() is True:
                user_pwd_form = password_change_form.save()
                update_session_auth_hash(request, user)  # Important!
                user_pwd_form.save()

            context = {
                'uform': user_form,
                'pform': user_profile_form,
                'pwdform': password_change_form,
                'user': user,
            }

            return render(request, 'accounts/user_settings.html', context)

1 个答案:

答案 0 :(得分:0)

似乎您不希望密码表单验证失败,除非填写了某些字段但不是全部字段。然而,如果任何字段留空,则通过制作所需的字段django将无法通过验证。因此,您应该做的是创建所有表单字段required=False,然后在密码表单中添加clean方法,如下所示:

from django.core.exceptions import ValidationError

def clean(self):
    data = super(MyPasswordChangeForm, self).clean()

    # if django field validation already failed, don't do any more validation
    # because the field values we need to check might not be present.
    if self.errors:
        return data

    # you could do this a lot of different ways, some of them simpler probably...
    fields = ('old_password', 'new_password1', 'new_password2')
    for fn in fields:
        # if any field contains data
        if data[fn]:
            for fn in fields:
                # if any field does not contain data
                if not data[fn]:
                    raise ValidationError("All fields must be filled in.")
            break
    return data

这样,如果用户未填写changepassword表单上的任何字段,则验证不会失败。然后,如果你想知道这个人是否真的想要更改密码,你必须在你的视图中做一些事情,如:

if form.cleaned_data['new_password1']:
    # put code here to change the users password

请注意,我没有测试此代码,因此它可能不完美,但它应该非常接近您的需要。

在Django表单中,clean方法是它们为您提供涉及多个字段的表单验证的钩子。例如,如果两个数字输入必须加起来为第三个数字,那是你要检查的地方。如果表单输入有任何问题,请引发ValidationError异常,Django将在表单上显示验证错误。

相关问题