2011-07-25 6 views
0

Userモデルのプロファイルモデルとして使用しているPersonnelというモデルがあります。ここに私のモデルカスタム外部キープロパティ

私はのModelFormで上記のモデルを使用する必要が
class Personnel(models.Model): 
    user = models.OneToOneField(
     User 
    ) 
    phone = models.CharField(
     null=False, max_length=50, verbose_name="Phone" 
    ) 

です。ここに私のModelFormです:

class PersonnelForm(forms.ModelForm): 
    class Meta: 
     model = Personnel 
     exclude = ('user') 

    def __init__(self, *args, **kwargs): 
     personnel = Personnel(user=User.objects.create(username=(''.join(choice(ascii_uppercase + digits) for x in range(30))))) 
     super(PersonnelForm, self).__init__(
      instance=personnel, *args, **kwargs 
     ) 

私はので、私はそれを除外していますから、ウェブ上に表示されるuserフィールドを必要といけません。しかし、私はまだPersonnelFormのインスタンスをPersonnelインスタンスに渡して開始するために値を渡す必要があります。 Userモードにはemailというフィールドがありますが、これはユーザーが入力する必要がありますが、このフィールドは私のPersonnelモデルのフィールドでは表示されません。

という仮想フィールドを作成して、user.emailフィールドの値を設定し、取得すると、同じ値を取得できますか?そのような何か:

@property 
def email(): 
    def fget(self): 
     return 'fff' 

    def fset(self, email): 
     self.user.email = email 

I''lがDjango's generic CRUD viewsPersonnelFormを使用するので、私は上記のスニペットに似たいくつかの方法でそれを必要とします。

ありがとうございました。これは、作成に適しています

class PersonnelForm(forms.ModelForm): 

    email = forms.EmailField(
     required=True, label=_("Email") 
    ) 

    class Meta: 
     model = Personnel 
     exclude = ('user') 

    def save(self, *args, **kwargs): 
     commit = kwargs.get('commit', True) 
     kwargs['commit'] = False 
     personnel = super(PersonnelForm, self).save(*args, **kwargs) 
     if not personnel.user: #To prevent creating a new user when updating. 
      user = User.objects.create_user(
       email=self.cleaned_data['email'], 
       username=(''.join(choice(ascii_uppercase + digits) for x in range(30))), 
      ) 
     if commit: 
      personnel.save() 
     return personnel 

:ダニエルのアドバイスを使用して

(それは同様他人の利益を得ることができるように、タイトルのためのより良い名前を編集して提案すること自由に感じて下さい。)


ModelFormを使用して新しいレコードを作成しましたが、更新するときに電子メールを更新したり、電子メールを表示したりすることはできません。

+0

:あなたはこのロジックを実行するビューを変更したくないことを考えると

(IMOが間違っ決定であるが、それはあなたのコードだもの)、あなたは上書きsave方法でこれを行うことができますPersonnelFormからプロパティを除外したため、ユーザーの値を渡す必要はありません。 – Brandon

+0

Brandon、私はユーザーフィールドを除外しないと、 'Personnel'レコードを作成する私のフォームのドロップダウンリストを私に与えます。私は 'Personnel'レコードを作成し、自動的に' User'を作成する必要があります。それぞれの 'User record'にはランダムな' username'があり、 'password'にはnullがあります。後でそれを扱いますが、メールアドレスを指定できるようにする必要があります。 –

+0

私は完全に理解しています。 Userオブジェクトを作成し、プロパティの混乱を起こさずにプロパティを設定することができます。 Userオブジェクトを作成できる場所は、Personnelオブジェクトのsaveメソッド、Personnelフォームを処理するビュー、またはPersonnelクラスに添付されたpost_save信号でも少なくとも3つあります。 – Brandon

答えて

1

あなたの質問には2つの誤解があります。まず、除外してもフィールドの値を渡す必要があること。第二に、モデルにないフィールドを含めることができないということです。これらはどちらも当てはまりません。

別のemailフィールドを定義し、実際のモデルフィールドと共にフォームに表示し、後でその値を使用してUserオブジェクトを作成することは間違いありません。あなたは

class PersonnelForm(forms.ModelForm): 
    email = forms.CharField() 

    class Meta: 
     model = Personnel 
     exclude = ('user',) 

    def save(self, *args, **kwargs): 
     # call super method with commit=False, but remember original commit arg 
     commit = kwargs.get('commit', True) 
     kwargs['commit'] = False 
     new_object = super(PersonnelForm, self).save(*args, **kwargs) 
     user = User.objects.create_user(
      email=self.cleaned_data['user'], 
      username=get_random_username(), 
      password=User.objects.make_random_password() 
     ) 
     new_object.user = user 
     # now save if commit was not explicitly set to False 
     if commit: 
      new_object.save() 
     return new_object 
+0

乾杯。それがそれでした。私はModelFormに追加フィールドを追加することはできないという印象を受けましたが、そうすることができます。 –

+0

私はちょっとした不具合に遭遇しました。あなたは、新しいレコードを作成しているときにメソッドが機能しているように見えますが、ModelFormを使用してそのレコードを更新するときに、新しい「User」を作成しようとします。これを回避するために、単純な 'if'節を追加しました。 (編集を参照)。私が現在解決できないもう一つの問題は、更新時に 'personnel.user.email'フィールドの値を表示する方法です。すべてのフィールドは 'Personnel'レコードから直接更新されますが、' email'は 'User'モデルにあります。 –