我正在使用Django注册,与其他人不同,我似乎有相反的问题。我的用户对象保存得很好,但我的UserProfile对象不是!
我关注了这个网站:
http://birdhouse.org/blog/2009/06/27/django-profiles/
这真的很好,现在我有了:
class ProfileForm(forms.ModelForm):
YESNO = [
(True,mark_safe('<img src="/static_files/greenTick.png"/>')),
(False,mark_safe('<img src="/static_files/redCross.png"/>'))]
class Meta:
model = UserProfile
exclude = ('isTweeting','points','user')
fields = ('display_name','first_name','last_name','email','gravatar')
def __init__(self, *args, **kwargs):
super(ProfileForm, self).__init__(*args, **kwargs)
self.fields['email'].initial = self.instance.user.email
self.fields['first_name'].initial = self.instance.user.first_name
self.fields['last_name'].initial = self.instance.user.last_name
self.fields['display_name'].initial = self.instance.user.username
self.fields['gravatar'].initial = self.instance.usesGravatar
#add in the input to size it juuuuust right.
email = forms.EmailField(label="Primary email",help_text='',widget=forms.TextInput(attrs={'class': 'wideInput'}))
first_name = forms.Field(label="First name",help_text='',required=False,widget=forms.TextInput(attrs={'class': 'wideInput'}))
last_name = forms.Field(label="Last name",help_text='',required=False,widget=forms.TextInput(attrs={'class': 'wideInput'}))
display_name = forms.Field(label="Display name",help_text='',widget=forms.TextInput(attrs={'class': 'wideInput'}))
gravatar = ImgModelChoiceField(label='Gravatar', choices=YESNO, widget=forms.RadioSelect(renderer=ImgRadioFieldRenderer))
def save(self, *args, **kwargs):
"""
Update the primary email address on the related User object as well.
"""
u = self.instance.user
u.email = self.cleaned_data['email']
u.username = self.cleaned_data['display_name']
u.first_name = self.cleaned_data['first_name']
u.last_name = self.cleaned_data['last_name']
u.save()
self.instance.gravatar = (self.cleaned_data['gravatar'] == 'True')
profile = super(ProfileForm, self).save(*args,**kwargs)
return profile
此对象作为form_class传递到Django-profile中,如上面的网站所述。我遇到的问题是,当我提交表单时,“用户”数据正确更新 - 电子邮件中的任何更改或什么传播到数据库 - 都不会发送对“gravatar”值的更改。也没有抛出任何错误。
我应该做些什么?
答案 0 :(得分:1)
我要冒这个猜测
def save(self, *args, **kwargs):
...
self.instance.gravatar = (self.cleaned_data['gravatar'] == 'True')
profile = super(ProfileForm, self).save(*args,**kwargs)
return profile
您似乎正在使用自定义窗口小部件,并且需要先将字符串'True'
(从窗体传回)更改为布尔值True
,然后再将其保存到数据库中。当您在下一行拨打save()
时,ModelForm
将直接从表单的self.instance.gravatar
覆盖您提供的cleaned_data
值:
https://github.com/django/django/blob/master/django/forms/models.py#L351
此外,在__init__
中,您不需要包含
self.fields['gravatar'].initial = self.instance.usesGravatar
因为当您在视图中实例化表单以及实例时,此字段已绑定到模型表单并将自动填充(例如,如果正在编辑UserProfile
)。
最后,在Meta
中,您不需要同时包含excludes
和fields
,其中一个应该没问题。
答案 1 :(得分:1)
首先考虑@Timmy的建议。 唯一应该注意的是这一行:
profile = super(ProfileForm, self).save(*args,**kwargs)
默认情况下,save
方法有commit=True
。验证调用此表单的函数是否可能在commit=False
或args
中发送kwargs
。如果是,那么您必须在返回之前手动保存配置文件profile.save()
,因为commit=False
表示更改不会反映到数据库。
为什么您允许用户更新用户名和电子邮件?如果您允许更新这两个字段,您将如何跟踪注册过程?通常用户使用他们的电子邮件注册。定义您希望保持不变的字段(用户名或电子邮件)的标准。
<强>更新强>
此外,您在保存功能中又犯了一个错误。您正在更新用户从instance.user
获取的电子邮件,用户名,名字和姓氏。但是,在配置文件表单默认保存时覆盖的那个实例在此处调用profile = super(ProfileForm, self).save(*args,**kwargs)
。您应该使用user = profile.user
profile
super
更新这些字段。您的save
函数应如下所示:
def save(self, *args, **kwargs):
"""
Update the primary email address on the related User object as well.
"""
profile = super(ProfileForm, self).save(*args,**kwargs)
u = profile.user
u.email = self.cleaned_data['email']
u.username = self.cleaned_data['display_name']
u.first_name = self.cleaned_data['first_name']
u.last_name = self.cleaned_data['last_name']
u.save()
#profile.save() #if commit=False in kwargs
return profile