django - django modelform 覆盖 save() 方法 self.instance 已更改
问题描述
我正在制作用户信息页面。
在视图中,我通过这样的request.user
形式
form = UserForm(request.POST, instance=request.user)
问题是,当我用 保存表单时form.save()
,用户名已更改,并且我已签self.isntance
入,但UserForm
我发现方法self.instance.username
中的save()
已更改,但字段的干净方法(clean_username()
)和表单子类的clean()
方法中没有。
self.instance.username
只是在save()
方法上有所改变。
我有另一个带有 Usermodel 的字段,例如电子邮件字段,但只有用户名字段被更改。
任何建议或线索对我都有好处
附言。在我写完这个问题之后,我发现方法中的另一件事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()
谢谢
解决方案
您可以从 访问原始值self.initial
,也就是说,如果您向表单提供了初始值。
推荐阅读
- python-3.x - PyQt:在当前命令的撤消期间从 UndoStack 弹出先前的命令
- mongodb - Parse Server 应用程序的 MongoDB 索引
- asp.net-mvc - 无法让 MVC 在 asp.net Web 表单项目中工作
- c# - DateTimeStyles 和 WhiteSpaces 字符
- python - 与 gitlab-ci 中的父范围 docker 容器共享 docker 容器中的目录?
- c# - Winforms C#中的TextBoxGrid/表格视图
- sql - SQL - 如何匹配值?
- .net - 使用 netstandard2.0 读取应用程序配置详细信息的推荐方法是什么
- matlab - Matlab 轴在负极限值上抛出错误
- angular6 - RxJs 间隔与 takeUntil 发布最后一个值