2009-11-13 13 views
20

もし私の質問がかなり明白で、ほとんど全ての開発者がUserProfileで働いていると答えてください。first_name、last_nameを変更してDjangoでUserProfileフォームを作成するにはどうすればいいですか?

しかし、私はdjangoのマニュアルやDjangoブックで助けを見つけることができませんでした。

DjangoフォームでUserProfileフォームを実行する場合は、プロファイルフィールドと一部のUserフィールドを変更する必要があります。

しかし、forms.UserProfileForm(まだ?)はありません!

どうすればよいですか?ここで

答えて

32

は、私はついにやった方法です:

class UserProfileForm(forms.ModelForm): 
    first_name = forms.CharField(label=_(u'Prénom'), max_length=30) 
    last_name = forms.CharField(label=_(u'Nom'), max_length=30) 

    def __init__(self, *args, **kw): 
     super(UserProfileForm, self).__init__(*args, **kw) 
     self.fields['first_name'].initial = self.instance.user.first_name 
     self.fields['last_name'].initial = self.instance.user.last_name 

     self.fields.keyOrder = [ 
      'first_name', 
      'last_name', 
      ...some_other... 
      ] 

    def save(self, *args, **kw): 
     super(UserProfileForm, self).save(*args, **kw) 
     self.instance.user.first_name = self.cleaned_data.get('first_name') 
     self.instance.user.last_name = self.cleaned_data.get('last_name') 
     self.instance.user.save() 

    class Meta: 
     model = UserProfile 
+0

「メディア」とは、「メタ」とします。 – Daishiman

+0

プロファイルがまだ作成されていない場合、この解決策は機能しません。私はそれのための修正を持っていないが、私はそれを投稿します。 –

+5

ここで説明する 'User'モデルで' post_save'シグナルを使用すると、これは起こりません:http://docs.djangoproject.com/ja/dev/topics/auth/#storing-additional-information-about-ユーザー – Natim

0

私はそれが正常なあなたは、単一のフォームに二つのモデルをマージすると、あなたがドキュメント内の任意の情報が見つからないことを取ります。

また、非常に明らかに次のことができます。ユーザーとユーザープロファイルの2つのモデルフォームを作成します。 userprofile modelformをfirstnameとlastnameだけを表示するように設定します。両方のフォームを単一の<form>タグ内の同じテンプレートに入れます。提出されたら、各フォームのsaveメソッドを呼び出します。

+0

はい、実際には2つのフォームを実際に使用するのは簡単ではありません...このソリューションでは、必要に応じてフィールドを注文し続けることはできません'{{form}}'。私が提供したソリューションでは、フォームフレームワークの使用を継続したいものは何でもできます。 – Natim

+0

私はちょうどモデルフォームの2つのモデルをマージするという考えが嫌いです。私の主観的な意見とは別に、私はあなたの解決策に対して具体的な異議を唱えておらず、両方の解決策に賛否両論があるようです。いつでも使用できます;) – shanyu

+0

私はあなたに同意しますが、この特定の問題を探すのは視点です。ユーザープロファイルとユーザーモデルは密接に関連しています。私の場合、UserProfileモデルは、Userモデルに欠落しているフィールドを追加する単なる方法です。また、プロファイルを更新する場合は、それらがUserProfileまたはUserモデルに含まれているかどうかにかかわらず、ユーザーのストックプロパティに結合されているため、これらのフィールドをすべて更新する必要があります。 – Natim

5

これは私が現在のトランク(改訂:11804)で行った方法です。 Natimの解決策は私のために働いていませんでした。 admin.py

forms.py
class ProfileAdmin(admin.ModelAdmin): 
    form = ProfileForm 

    def save_model(self, request, obj, form, change): 
     obj.user.first_name = form.cleaned_data['first_name'] 
     obj.user.last_name = form.cleaned_data['last_name'] 
     obj.user.save() 
     obj.save() 

class ProfileForm(forms.ModelForm): 
    first_name = forms.CharField(max_length=256) 
    last_name = forms.CharField(max_length=256) 

    def __init__(self, *args, **kwargs): 
     super(ProfileForm, self).__init__(*args, **kwargs) 
     try: 
      self.fields['first_name'].initial = self.instance.user.first_name 
      self.fields['last_name'].initial = self.instance.user.last_name 
     except User.DoesNotExist: 
      pass 

    class Meta: 
     fields = ['first_name', 'last_name', ...etc.] 
+0

あなたのProfileFormでは、プロファイルを保存することはできません。 Mineは管理者を変更しません。しかし、あなたはそうしますが、管理者なしでは使用できません。 – Natim

+0

プロファイルを '' obj.save() ''で保存します。あなたが正しいのは管理者だけです。私はそれをそれに組み込む必要がありました。 あなたのアプリで動作するためには。 adminからフォームにロジックを移動する必要があるビューを表示します。あなたが '' save''メソッドでやったように。 – wunki

0

バックエンドに2つのモデルのフォームを持っているだけで、あなたのテンプレートに単一のフォームとしてそれらを提示しないのはなぜ? UserProfileFormから名前フィールドを削除し、ユーザーオブジェクトの2番目のモデルフォームを作成しますか?

+0

それは悪い考えではありません。しかし、1つのフォームしか持たない方が便利です。 – Natim

+0

私はそう思うさまざまなアプローチ。私は、上記で説明したものとまったく同じです。なぜなら、複数のDjangoフォームオブジェクトを使用する方が、互いに独立して再利用できるようになり、処理がより洗練されたからです(IMHO)。 明確にするために、私はページ上に複数のHTMLフォームについて話しているわけではありません。それはユーザーのための1つのフォームのように見えます。 – Tom

1

また、プロファイルのアプリを持っているジャンゴ - 基本アプリケーションプロジェクトを使用しようとすることができます:私は今日、この偶然見つけ、いくつかのグーグルでの後、私は少しクリーナーで解決策を見つけた

https://github.com/nathanborror/django-basic-apps

+0

これは、UserProfileとdjangoから組み合わせたformsetを作成しない理由ではありません。ユーザーモデル/ – Denis

35

を私の意見では:

#in forms.py 
class UserForm(forms.ModelForm): 
    class Meta: 
     model = User 
     fields = ["username", "email"] 

class UserProfileForm(forms.ModelForm): 
    class Meta: 
     model = UserProfile 

#in views.py 
def add_user(request): 
    ... 
    if request.method == "POST": 
     uform = UserForm(data = request.POST) 
     pform = UserProfileForm(data = request.POST) 
     if uform.is_valid() and pform.is_valid(): 
      user = uform.save() 
      profile = pform.save(commit = False) 
      profile.user = user 
      profile.save() 
      .... 
    ... 

#in template 
<form method="post"> 
    {{ uform.as_p }} 
    {{ pform.as_p }} 
    <input type="submit" ...> 
</form> 

Source

+0

これは別の解決策ですが、必要に応じてフィールドを注文することはできません。例えば、私は 'title'フィールドをfirst_nameとlast_nameの前に置くべきですが、まだpformの部分です。 – Natim

+0

Natim、できますが、それはあなたの手で行う必要があります:) –

+0

フィールドの順序を指定することができます...あなたがレンダリングを自分で行う限り、ns-keipとして言及します。https: //docs.djangoproject.com/ja/1.8/topics/forms/#rendering-fields-manually –

1

これは私が長いバックうまくいけば1つの私のプロジェクトで使用されるものです他の人たちがこの問題に取り組むのを助けてくれるはずです。

class SignUpForm(forms.ModelForm): 
    first_name = forms.CharField(max_length = 30) 
    last_name = forms.CharField(max_length = 30) 
    username = forms.CharField(max_length = 30) 
    password = forms.CharField(widget = forms.PasswordInput) 
    password1 = forms.CharField(widget = forms.PasswordInput) 
    class Meta: 
     model = UserProfile 
     exclude = ['user'] 

    def clean_username(self): # check if username does not exist before 
     try: 
      User.objects.get(username=self.cleaned_data['username']) #get user from user model 
     except User.DoesNotExist : 
      return self.cleaned_data['username'] 

     raise forms.ValidationError("This user exist already choose an0ther username") 



    def clean(self, *args , **kwargs): 
     super(SignUpForm).clean(*args ,**kwargs) # check if password 1 and password2 match each other 
     if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:#check if both pass first validation 
      if self.cleaned_data['password1'] != self.cleaned_data['password2']: # check if they match each other 
       raise forms.ValidationError("Passwords don't match each other") 

     return self.cleaned_data 
    def save(self): # create new user 
     new_user = User.objects.create_user(username=self.cleaned_data['username'],password=self.cleaned_data['password1'],email=self.cleaned_data['email']) 
     new_user.first_name = self.cleaned_data['first_name'] 
     new_user.last_name = self.cleaned_data['last_name'] 
     new_user.save() 
     UserProf = super(SignUpForm,self).save(commit = False) 
     UserProf.user = new_user 
     UserProf.save() 
     return UserProf 
関連する問題