1

シナリオ:

私はこのようなモデルを持っています:

class A(models.Model):
    ...

class B(models.Model):
    a = models.ForeignKey(A)
    ...

管理者には次のようなものがあります。

class AInlinde(admin.StackedInline):
    ...
    model = A
    ...

class BAdmin(admin.ModelAdmin):
     ...
     inlines = [AInline]
     ...

ユーザーがインラインでモデルを削除したときにログに記録する必要がありますが、コードをたどることができません。これまでBadmin、メソッドがありますsave_formset。これは次のとおりです。

def save_formset(self, request, form, formset, change):
    """
    Given an inline formset save it to the database.
    """
    formset.save()

formsetしかし、それはメソッドによって生成されると思うmodelformset_factoryので、そのフォームセットの削除動作をいつオーバーライドできるかわかりません

4

3 に答える 3

3

2017年にソフト削除とログ削除を探している人のために。最近のdjango1.11では、 delete_existingメソッドをオーバーライドできます。

通常のフォームセットの場合

class SoftDeleteModelFormSet(BaseModelFormSet):
    def delete_existing(self, obj, commit=True):
        """Deletes an existing model instance."""
        if commit:
            obj.deleted_at = datetime.datetime.now()
            obj.save()

            # log here

関連モデルの場合

class SoftDeleteInlineFormSet(BaseInlineFormSet):
    def delete_existing(self, obj, commit=True):
        """Deletes an existing model instance."""
        if commit:
            obj.deleted_at = datetime.datetime.now()
            obj.save()

            # log here

そして、新しいフォームセットでmodelformset_factoryを使用します

product_formset = modelformset_factory(
    ...
    formset = SoftDeleteModelFormSet,
    ...
)
于 2017-07-27T04:09:18.583 に答える
2

フォームセットがオブジェクトを保存または削除する方法をオーバーライドするための最良の方法は、メソッドとメソッドを継承しBaseInlineFormSetてオーバーライドするクラスを作成することです。savesave_existing_objects

class NoDeleteFormset(BaseInlineFormSet):
    def save(self, commit=True, request=None):
        """Saves model instances for every form, adding and changing instances
        as necessary, and returns the list of instances.
        """
        if not commit:
            self.saved_forms = []
            def save_m2m():
                for form in self.saved_forms:
                    form.save_m2m()
            self.save_m2m = save_m2m
        return self.save_existing_objects(commit) + self.save_new_objects(commit)

    def save_existing_objects(self, commit=True, request=None):
        self.changed_objects = []
        self.deleted_objects = []
        if not self.initial_forms:
            return []

        saved_instances = []
        for form in self.initial_forms:
            pk_name = self._pk_field.name
            raw_pk_value = form._raw_value(pk_name)

            # clean() for different types of PK fields can sometimes return
            # the model instance, and sometimes the PK. Handle either.
            pk_value = form.fields[pk_name].clean(raw_pk_value)
            pk_value = getattr(pk_value, 'pk', pk_value)

            obj = self._existing_object(pk_value)
            if self.can_delete and self._should_delete_form(form):
                self.deleted_objects.append(obj)
                obj.deleted_at = datetime.now()
                obj.save()

                # log there your user deleting the object!

                continue
            if form.has_changed():
                self.changed_objects.append((obj, form.changed_data))
                saved_instances.append(self.save_existing(form, obj, commit=commit))
                if not commit:
                    self.saved_forms.append(form)
        return saved_instances

次に、から継承するクラスを作成しStackedInlineます。

class MetaInline(StackedInline):
    formset = NoDeleteFormset
    ...
于 2012-06-10T16:31:20.177 に答える
0

ModelAdminデフォルトの削除動作をカスタマイズする必要はありません。モデルに接続django.db.models.signals.post_deleteし、モデルが削除された後にフックを取得して、そこに記録するだけです。

于 2012-05-27T07:26:56.923 に答える