0

管理画面での更新時に空欄になっている場合に備えて、manytomany フィールドにデフォルトの項目リストを追加したいと考えています。

私の問題は、save、save_model、または post_save シグナルをオーバーライドして manytomany フィールドを変更しても、django はまだ子関係の保存を完了しておらず、親のみを保存しているため機能しないことです (例: Django: 多対多のカスタム保存メソッド関係)。他の投稿で提案されている解決策である信号 m2m_changed を試しましたが、リストが空白のままになっていると変更されないため、トリガーされません!

メソッドのオーバーライドとシグナルで行き止まりに達したように見えるので、別のアプローチを考えられる人はいますか? フォームが管理者に表示される前または後にデフォルトのリストが追加されるかどうかは気にしません。

アップデート

うまくいかなかったもの:

(Fixtures は私の m2m フィールドの名前です)。

さまざまな方法をオーバーライドして、以下の提案を試しました。このトレースから、フィクスチャが追加され、admin およびモデルの多くのメソッドを通じて表示されることがわかりますが、これらのメソッドが呼び出された後、フィクスチャは削除され、置き換えられます。オーバーライドできる after_everything_else メソッドはないようです。

[Wed Sep 18 15:24:06 2013] [error]  in save of model fixture count =  0
[Wed Sep 18 15:24:06 2013] [error]  in save of overriden admin model form  fixture count =  15
[Wed Sep 18 15:24:06 2013] [error]  in save_model of admin fixture count =  15
[Wed Sep 18 15:24:06 2013] [error]  in save of model fixture count =  15

何が機能したか

管理フォームをオーバーライドし、そこに clean_fixtures メソッドを配置します。clean_fixtures は呼び出されず、管理リソースに配置されるだけです。次のようにオーバーライドされた形式である必要があります。

class RankingUpdateForm(forms.ModelForm):


    def clean_fixtures(self):

        data = self.cleaned_data['fixtures']

        # add default set of fixtures if none already there
        if len(data) == 0:

            return get_default_fixtures()

        else:
            return data

class RankingUpdateAdmin(admin.ModelAdmin):


    list_display = ('rank_type','date', 'comment', 'issued')
    form = RankingUpdateForm


    def clean_fixtures(self):

         assert False, "I'm never called!"

    def save_formset(self):
         assert False, "I'm never called either!"
4

2 に答える 2

1

管理フォームをオーバーライドして、ManyToMany フィールドのフォームの clean メソッドにロジックを実装できます。たとえば。

def clean_recipients(self):
    data = self.cleaned_data['recipients']

    if not data:
        # return default recipients if the selected list is empty.
        data =  [r.pk for r in Recipient.objets.all()]  #just an example, you can alter this query to select your defaults

    return data

アップデート

save メソッドをオーバーライドして受信者を保存する

def save(self, commit=True):
    instance = forms.ModelForm.save(self, False)

    old_save_m2m = self.save_m2m
    def save_m2m():
       old_save_m2m()
       instance.recepient_set.clear()
       for recepient in self.cleaned_data['recepients']:
           instance.recepient_set.add(recepient)
    self.save_m2m = save_m2m

    if commit:
        instance.save()
        self.save_m2m()

    return instance
于 2013-09-10T19:09:01.757 に答える