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

上記のWebサイトで説明されているように、このオブジェクトはform_classとしてDjango-profileに渡されて使用されます。私が抱えている問題は、フォームを送信すると、「ユーザー」データが正しく更新されている間(電子メールの変更やデータベースに反映されないもの)、「gravatar」値の変更が送信されないことです。また、エラーはスローされません。

私が何をすべきかアイデアはありますか?

4

2 に答える 2

1

まず、@Timmy からの提案を検討してください。他に注目すべき唯一のことは、次の行にあります。

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

デフォルトでは、saveメソッドにはcommit=True. このフォームを呼び出している関数がまたはを送信commit=Falseしている可能性があることを確認してください。はいの場合、変更がデータベースに反映されないため、戻る前にプロファイルを手動で保存する必要があります。argskwargsprofile.save()commit=False

また、なぜユーザーがユーザー名と電子メールの両方を更新できるようにしているのですか? 両方のフィールドの更新を許可している場合、登録プロセスをどのように追跡しますか? 通常、ユーザーはメールを使用してサインアップします。変更しないフィールド (ユーザー名または電子メール) を定義します。

アップデート

また、保存機能でもう1つ間違ったことをしています。から取得したユーザーの電子メール、ユーザー名、姓名を更新していますinstance.user。ただし、プロファイル フォームのデフォルトの保存が call here である場合、そのインスタンスは上書きされます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 に答える
1

ここで推測を危険にさらすつもりです

def save(self, *args, **kwargs):
    ...

    self.instance.gravatar = (self.cleaned_data['gravatar'] == 'True')
    profile = super(ProfileForm, self).save(*args,**kwargs)
    return profile

カスタム ウィジェットを使用しているようで、DB に保存する前に文字列'True'(フォームから返された) をブール値に変更する必要があるようです。ただし、次の行でTrue呼び出すと、指定した値がフォームの から直接データで上書きされます。save()ModelFormself.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両方を含める必要はありません。どちらか一方を使用してもかまいません。excludesfields

于 2012-07-06T10:56:04.430 に答える