1

我正在使用 Django 注册,与其他人不同,我似乎遇到了相反的问题。我的 User 对象保存得很好,但我的 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”值的更改。也不会抛出错误。

有什么想法我应该做什么?

4

2 回答 2

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.gravatarcleaned_data

https://github.com/django/django/blob/master/django/forms/models.py#L351


此外,在 中__init__,您不需要包括

self.fields['gravatar'].initial = self.instance.usesGravatar

因为此字段已经绑定到模型表单,并且UserProfile当您实例化表单以及视图中的实例时将自动填充(例如,如果正在编辑)。


最后,在您的 中Meta,您不需要同时包含excludesand fields,一个或另一个应该没问题。

于 2012-07-06T10:56:04.430 回答
1

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

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

默认情况下,该save方法具有commit=True. 验证调用此表单的函数可能正在commit=False发送argskwargs。如果是,那么您必须profile.save()在返回之前手动保存配置文件,因为这commit=False意味着更改不会反映到数据库。

为什么您允许用户同时更新用户名和电子邮件?如果您允许更新这两个字段,您将如何跟踪注册过程?通常用户使用他们的电子邮件注册。定义您希望保持不变的字段(用户名或电子邮件)的标准。

更新

此外,您在保存功能中又做错了一件事。您正在更新来自 的用户中的电子邮件、用户名、名字和姓氏instance.user。但是当在此处调用配置文件表单默认保存时,该实例被覆盖profile = super(ProfileForm, self).save(*args,**kwargs)。您应该做的是使用由返回的user = profile.userThe更新这些字段。您的函数应如下所示:profilesupersave

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
于 2012-07-07T05:30:03.437 回答