1. ホーム
  2. python

[解決済み] Django の管理画面で同じモデルに対して複数の ModelAdmins/view を表示する

2022-04-20 06:21:44

質問

同じモデルに対して複数の ModelAdmin を作成し、それぞれ異なるカスタマイズを行い、異なる URL にリンクさせるにはどうすればよいですか?

例えば、 Posts という Django のモデルを持っているとします。デフォルトでは、このモデルの管理画面は全ての Post オブジェクトを一覧表示します。

list_display のような変数を設定することで、ページに表示されるオブジェクトのリストをさまざまな方法でカスタマイズできることは知っています。 queryset というように、ModelAdminのメソッドに追加することができます。

class MyPostAdmin(admin.ModelAdmin):
    list_display = ('title', 'pub_date')

    def queryset(self, request):
        request_user = request.user
        return Post.objects.filter(author=request_user)

admin.site.register(MyPostAdmin, Post)

デフォルトでは、これはURLでアクセスできるようになります。 /admin/myapp/post . しかし、私は同じモデルの複数のビュー/モデル管理者を持ちたいと考えています。 /admin/myapp/post はすべての投稿オブジェクトをリストアップし /admin/myapp/myposts は、そのユーザーに属するすべての投稿をリストアップし /admin/myapp/draftpost は、まだ公開されていないすべての投稿をリストアップすることができます。(これらは単なる例です。私の実際のユースケースはもっと複雑です)

同じモデルに対して、複数の ModelAdmin を登録することはできません。 AlreadyRegistered 例外が発生します)。理想的には、次のように実現したいです。 なし は、すべてを一つの ModelAdmin クラスにまとめ、URL に応じて異なるクエリセットを返すように独自の 'urls' 関数を記述します。

Django のソースを見たところ、以下のような関数がありました。 ModelAdmin.changelist_view をどうにかして私のurls.pyに含めることができますが、それがどのように機能するのか正確にはわかりません。

更新情報 : 私が望むことを行うための1つの方法を見つけました(下記参照)が、私はまだ他の方法を聞きたいと思っています。

どのように解決するのですか?

各モデルが一度しか登録できないという事実を回避するためにプロキシモデルを使用することで、私が望むことを実現する一つの方法を見つけました。

class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'pubdate','user')

class MyPost(Post):
    class Meta:
        proxy = True

class MyPostAdmin(PostAdmin):
    def get_queryset(self, request):
        return self.model.objects.filter(user = request.user)


admin.site.register(Post, PostAdmin)
admin.site.register(MyPost, MyPostAdmin)

次に、デフォルトの PostAdmin でアクセスできるようになります。 /admin/myapp/post で、そのユーザーが所有する投稿の一覧は /admin/myapp/myposts .

を見てから http://code.djangoproject.com/wiki/DynamicModels ということで、同じことをするために、以下のようなユーティリティ関数を思いつきました。

def create_modeladmin(modeladmin, model, name = None):
    class  Meta:
        proxy = True
        app_label = model._meta.app_label

    attrs = {'__module__': '', 'Meta': Meta}

    newmodel = type(name, (model,), attrs)

    admin.site.register(newmodel, modeladmin)
    return modeladmin

これは、次のように使うことができます。

class MyPostAdmin(PostAdmin):
    def get_queryset(self, request):
        return self.model.objects.filter(user = request.user)

create_modeladmin(MyPostAdmin, name='my-posts', model=Post)