使用django-registration保存userProfile

时间:2012-06-28 23:53:33

标签: python django

我正在使用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”值的更改。也没有抛出任何错误。

我应该做些什么?

2 个答案:

答案 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中,您不需要同时包含excludesfields,其中一个应该没问题。

答案 1 :(得分:1)

首先考虑@Timmy的建议。 唯一应该注意的是这一行:

profile = super(ProfileForm, self).save(*args,**kwargs)

默认情况下,save方法有commit=True。验证调用此表单的函数是否可能在commit=Falseargs中发送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