django modelform重写save()方法self.instance已更改

时间:2018-05-02 05:05:08

标签: django modelform

我正在制作用户信息页面。

在视图中,我将request.user传递给此类

form = UserForm(request.POST, instance=request.user)

问题在于,当我使用form.save()保存表单时,用户名已更改,我在self.isntance中检查UserForm,而不是self.instance.username save() 1}}方法已更改,但不在字段的clean方法(clean_username())和表单子类的clean()方法中。 self.instance.username仅在save()方法中更改。

我有另一个字段,其中包含Usermodel,如电子邮件字段,但只更改了用户名字段。

任何建议或线索对我都有好处

PS。在我写完这个问题后,我发现self.instance方法中的save()不是原始用户实例。 它的用户名和电子邮件是request.POST数据。

这是我的代码

视图

@login_required(login_url='/member/login')
def change_user_info(request):
    if request.method == 'POST':
        form = UserForm(request.POST, instance=request.user)
        if form.is_valid():
            form.save()
            update_session_auth_hash(request, form.instance)
            return redirect('/member/change-user-info')
    else:
        form = UserForm(instance=request.user)
    context = {
        'form': form,
        'home_button': True
    }
    return render(request, 'member/user_info.html', context)

模型

class User(AbstractUser):
    username = models.CharField(max_length=50, unique=True)
    email = models.EmailField()


    USERNAME_FIELD = 'username'
    EMAIL_FIELD = 'email'

形式

class UserForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        field_list = ['username', 'email']
        for field in field_list:
            self.fields[field].required = False

    new_password1 = forms.CharField(
        required=False,
        widget=forms.PasswordInput(
            attrs={
                'autofocus': True,
                'id': 'userinfo-new-password1',
                'class': 'form-control',
                'placeholder': '새 비밀번호',
                'aria-describedby': 'newpassword1HelpBlock',
            }),
    )
    new_password2 = forms.CharField(
        required=False,
        widget=forms.PasswordInput(
            attrs={
                'autofocus': True,
                'id': 'userinfo-new-password2',
                'class': 'form-control',
                'placeholder': '새 비밀번호 확인',
                'aria-describedby': 'newpassword2HelpBlock',
            }),
    )
    old_password = forms.CharField(
        required=False,
        widget=forms.PasswordInput(
            attrs={
                'autofocus': True,
                'id': 'userinfo-old-password',
                'class': 'form-control',
                'placeholder': '기존 비밀번호',
                'aria-describedby': 'oldpasswordHelpBlock',
            })
    )

    class Meta:
        model = User
        fields = [
            'username',
            'email',
        ]
        widgets = {
            'username': TextInput(attrs={
                # 'readonly': True,
                'disabled': True,
                'autofocus': True,
                'id': 'disabledTextInput',
                'class': 'form-control',
                'aria-describedby': 'usernameHelpBlock',
            }),
            'email': EmailInput(attrs={
                'autofocus': True,
                'id': 'userinfo-email',
                'class': 'form-control',
                'placeholder': 'EMAIL',
                'aria-describedby': 'emailHelpBlock',
            }),
        }

    def clean_username(self):
        test = self.cleaned_data['username']  --> ''
        test2 = self.instance.username   --> has correct user name
        return test

    def clean_new_password1(self):
        if not self.cleaned_data.get('new_password1'):
            return None
        return self.cleaned_data['new_password1']

    def clean_new_password2(self):
        if not self.cleaned_data.get('new_password2'):
            return None
        return self.cleaned_data['new_password2']

    def clean_old_password(self):
        password = self.cleaned_data.get('old_password')
        if not self.instance.check_password(password):
            raise forms.ValidationError('정보 변경을 위해서 기존 비밀번호를 입력해 주세요')
        return password

    def clean(self):
        test = self.instance.username --> has correct username
        super().clean()
        new_password1 = self.cleaned_data.get('new_password1')
        new_password2 = self.cleaned_data.get('new_password2')

        if new_password1 and new_password2:
            if new_password1 != new_password2:
                raise forms.ValidationError(
                    "새 비밀번호가 일치하지 않습니다."
                )
        elif new_password1 is None and new_password2 is None:
            pass
        else:
            raise forms.ValidationError(
                "비밀번호 변경을 위해선 '새 비밀번호' '새 비밀번호 확인'란에 모두 입력하셔야 합니다."
            )

    def save(self, commit=True):
        user = self.instance
        username = self.instance.username --> ''
        email = self.instance.email --> has correct email
        if self.instance.email != self.cleaned_data.get('email'):
            user.email = self.cleaned_data.get('email')
        if self.cleaned_data['new_password2'] is not None:
            user.set_password(self.cleaned_data.get('new_password2'))
        user.save()

由于

1 个答案:

答案 0 :(得分:0)

表单中的用户名字段已被禁用,因为您在clean_username方法中的self.cleaned_data ['username']中获取了空白值。所以改变你的代码如下

def clean_username(self):
    return self.cleaned_data['username']  or self.instance.username