2011-12-11 3 views
0

SuperPersonインスタンスでfull_nameを設定する正しい方法を探しています。Django、他のAdminページの入力に基づいて、保存中にフィールドを自動設定する

class Suffix(models.Mode): 
    suffix = models.CharField(max_length=255) 
    def __unicode__(self): 
     return u'%s'%(self.suffix) 

class Person(models.Model): 
    first_name= models.CharField(max_length=255) 
    last_name= models.CharField(max_length=255) 
    suffixes= models.ManyToManyField(Suffix, blank=True, null=True) 
    full_name= models.CharField(max_length=255) 

class SuperPerson(Person): 
    ignore_this_field= model.CharField(max_length=255) 

FULL_NAMEは、管理ページでユーザーから隠され、自動的にヒットする管理ページが保存ボタンを管理ページ上の他の入力に基づいて更新されることがあります。

私はこれとバリエーションなどの保存上書きを試してみました:私は私のユースケースのために容認できないとする、二回管理画面で保存ボタンをヒットした場合

def save(self, *args, **kwargs): 
    # Attempt to get data into the database so I can access it 
    super(SuperPerson,self).save(*args,**kwargs) 

    self.full_name = self.first_name + self.last_name 
    for suf in self.suffixes.all(): 
     self.full_name+= suf.__unicode__() 

    # Now save the copy with full_name set as I wish 
    super(SuperPerson,self).save(*args,**kwargs) 

このメソッドは動作しますが、新しい自己のように思えます。管理ページから入力したサフィックスは、self.suffixes.all()を呼び出すと、最初のsuper.saveでデータベースに格納されませんでした。

私はfull_nameをデコレータでプロパティにしようとしましたが、full_nameを使ってPersonとSuperPersonのdbsをフィルタリングする必要があるため、誰かがプロパティでフィルタをかける方法を教えてくれないと動作しません。私はむしろdbに保存された値を持っています。

私はpre_saveとpost_save信号を試しました。どちらもうまくいきませんでした。

@receiver(pre_save, sender=SuperPerson) 
def set_full_name(sender, instance, **kwargs): 
    instance.full_name = instance.first_name + instance.last_name 

    for suf in instance.suffixes.all(): 
     instance.full_name+= ', ' + suf.__unicode__() 

編集:これは同じ効果があります。インスタンスの接尾辞は管理ページのものと一致しません。

他の入力に基づいてfull_nameを保存する正しい方法は何ですか?ああ、私はAdminフォームを使いこなすのを避けたいと思っています。

追加情報: 特に問題は、接尾辞フィールドが使用しようとしているときに更新されていないようです。現在の日付を表す文字列を追加するなど、full_nameを別のものに更新することはできますが、接尾辞にはアクセスできません。

おかげで、デイル

SOLUTION:

@receiver(m2m_changed, sender=Person.suffixes.through) 
def set_full_name_after_ManyToMany_saved(sender, instance, **kwargs): 
    instance.full_name = instance.first_name + instance.last_name 
    for suf in instance.suffixes.all(): 
     instance.full_name+= ', ' + suf.__unicode__() 
    print 'Saving As', instance.full_name 
    instance.save() 

私が代わりにSuperPerson、接尾辞またはPerson.suffixesのPerson.suffixes.throughを使用しなければならなかった理由を、私は好奇心が強い - これで良いドキュメントがありますどこかで、私はそれを見つけることができませんでした。そして、コードを4回実行しますが、少なくとも最終的な実行では正しい結果が得られます。ダニーとはBurhan

+0

あなたのコードはに 'pre_save'を結合さを'SuperPerson'、それは' Person'にバインドされるべきです –

+0

Personに直接バインドされたときにコードが実行されることはありませんが、上記のコメントを参照してください。 – dale

答えて

2

多くのおかげで、問題はあなたのM2Mのサフィックスとの関係、あるいは、むしろ管理者がM2Mの関係を保存しDjangoの方法です。あなたはそれがアトミックトランザクションではありません管理者フォームを経由してモデルを保存すると

かなり良い説明がWhy is adding site to an object doesn't seem to work in a save() override in the Django admin?

にこの答えです。メインオブジェクトが最初に保存され(PKがあることを確認するため)、M2Mはクリアされ、新しい値はフォームから出されたものに設定されます。

post_save()は実際にはまだ早すぎます。それがインスタンスが保存された場所で、関係は保存されません。

あなたはm2m_changed信号に接続する必要があります。https://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed

やModelAdminのはあなたに信号「すべてが完了したときに」与えジャンゴ1.4を待つ: https://code.djangoproject.com/ticket/16115

+0

それはうまくいきました、ありがとうございました。 – dale

+0

ありがとうございました。チケットが「すべて完了したとき」は初めてです。 –

関連する問題