2017-03-15 28 views
0

我能够成功更新这三种表单中的任何一种。但是,我的问题是,如果更改密码表单为空,则会在其上引发错误(如密码太短,当前密码不正确等),而不像其他形式,如果我保持不变,则不会发生错误。我怎样才能解决这个问题?我试着设置request.POST or None无济于事,而且我正在用尽想法。我也不使用{{ form.as_p }},而是逐场进行。这可能是一个问题吗?多个表单和一个在Django中提交。未提交表单上的错误

形式

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) 
+0

看起来这个表格不是强制性的,所以你应该检查表单是否有任何数据,然后验证它。或者使用其他方式来确定是否也提交了表单中的数据。 – Rohan

回答

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将在表单上显示验证错误。