28

私は次のようにadmin.pyを持っています:

  class profilesAdmin(admin.ModelAdmin):
     list_display = ["type","username","domain_name"]

オブジェクトを削除する前に、いくつかのアクションを実行したいと思います。

  class profilesAdmin(admin.ModelAdmin):
     list_display = ["type","username","domain_name"]

     @receiver(pre_delete, sender=profile)
     def _profile_delete(sender, instance, **kwargs):
        filename=object.profile_name+".xml"
        os.remove(os.path.join(object.type,filename))

このようなシグナル削除メソッドを使用するselfと、最初のパラメーターにする必要があるというエラーが表示されます。

上記の関数を変更するにはどうすればよいですか?
そして、削除されるオブジェクトの profile_name を取得したいと考えています。これはどのように行うことができますか?

また、delete_model メソッドをオーバーライドしようとしました。

def delete_model(self, request, object):
    filename=object.profile_name+".xml"
    os.remove(os.path.join(object.type,filename))
    object.delete()

ただし、複数のオブジェクトを一度に削除する必要がある場合、これは機能しません。

4

5 に答える 5

20

You're on the right track with your delete_model method. When the django admin performs an action on multiple objects at once it uses the update function. However, as you see in the docs these actions are performed at the database level only using SQL.

You need to add your delete_model method in as a custom action in the django admin.

def delete_model(modeladmin, request, queryset):
    for obj in queryset:
        filename=obj.profile_name+".xml"
        os.remove(os.path.join(obj.type,filename))
        obj.delete()

Then add your function to your modeladmin -

class profilesAdmin(admin.ModelAdmin):
    list_display = ["type","username","domain_name"]
    actions = [delete_model]
于 2013-03-04T07:27:40.687 に答える
6

主な問題は、Django 管理者の一括削除が instance.delete() ではなく SQL を使用していることです。管理者のみのソリューションの場合、次のソリューションは、Django 管理者の「本当にこれらを削除しますか」というインタースティシャルを保持します。

最も一般的な解決策は、モデルのマネージャーによって返されたクエリセットをオーバーライドして、削除をインターセプトすることです。

from django.contrib.admin.actions import delete_selected

class BulkDeleteMixin(object):
    class SafeDeleteQuerysetWrapper(object):
        def __init__(self, wrapped_queryset):
            self.wrapped_queryset = wrapped_queryset

        def _safe_delete(self):
            for obj in self.wrapped_queryset:
                obj.delete()

        def __getattr__(self, attr):
            if attr == 'delete':
                return self._safe_delete
            else:
                return getattr(self.wrapped_queryset, attr)

        def __iter__(self):
            for obj in self.wrapped_queryset:
                yield obj

        def __getitem__(self, index):
            return self.wrapped_queryset[index]

        def __len__(self):
            return len(self.wrapped_queryset)

    def get_actions(self, request):
        actions = super(BulkDeleteMixin, self).get_actions(request)
        actions['delete_selected'] = (BulkDeleteMixin.action_safe_bulk_delete, 'delete_selected', ugettext_lazy("Delete selected %(verbose_name_plural)s"))
        return actions

    def action_safe_bulk_delete(self, request, queryset):
        wrapped_queryset = BulkDeleteMixin.SafeDeleteQuerysetWrapper(queryset)
        return delete_selected(self, request, wrapped_queryset)

class SomeAdmin(BulkDeleteMixin, admin.ModelAdmin):
    ...
于 2014-10-03T15:35:50.057 に答える
1

複数のオブジェクトを削除するとdjangoが使用するため、delete_modelメソッドをオーバーライドしようとすると失敗しましたQuerySet.delete()。効率上の理由から、モデルのdelete()メソッドは呼び出されません。

あなたはそこにそれを見ることができますhttps://docs.djangoproject.com/en/1.9/ref/contrib/admin/actions/
最初を見る 警告

管理者はモデルのhttps://github.com/django/django/blob/master/django/contrib/admin/options.py#L1005delete_model()と同じですdelete()

したがって、複数のオブジェクトを削除する場合、delete メソッドが呼び出されることはありません。

あなたには双方向があります。

1. カスタム削除アクション。
選択した項目ごとに Model.delete() を呼び出すアクション。

2.信号を使用します。
クラス内ではなく、シグナルのみを使用できます。

この質問を見ることもできますDjango model: delete() not trigger

于 2016-03-19T15:34:14.770 に答える
1

あなたの方法は

class profilesAdmin(admin.ModelAdmin):
    #...

    def _profile_delete(self, sender, instance, **kwargs):
        # do something

    def delete_model(self, request, object):
        # do something

すべてのメソッド シグネチャ (通常は と呼ばれますself) の最初の引数として、現在のオブジェクトへの参照を追加する必要があります。また、delete_model はメソッドとして実装する必要があります。

于 2013-03-04T07:34:24.850 に答える