web-dev-qa-db-ja.com

Django adminの同じモデルの複数のModelAdmins / views

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

Django Postsというモデルがあります。デフォルトでは、このモデルの管理ビューにはすべてのPostオブジェクトがリストされます。

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

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。ただし、同じモデルの複数のビュー/ ModelAdminsが必要です。例:/admin/myapp/postはすべての投稿オブジェクトをリストし、/admin/myapp/mypostsはユーザーに属するすべての投稿をリストし、/admin/myapp/draftpostは、まだ公開されていないすべての投稿をリストする場合があります。 (これらは単なる例であり、私の実際のユースケースはより複雑です)

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

Djangoソースを見てきましたが、ModelAdmin.changelist_viewそれはどういうわけか私のurls.pyに含まれる可能性がありますが、それがどのように機能するのか正確にはわかりません。

更新:自分がやりたいことをする方法を見つけました(下記を参照)が、これを行う他の方法を聞きたいです。

142
Paul Stone

プロキシモデルを使用して、各モデルが1回だけ登録される可能性があるという事実を回避することで、目的を達成する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)
252
Paul Stone

ポールストーンの答えは絶対に素晴らしいです!ただ追加するため、Django 1.4.5 admin.ModelAdminからカスタムクラスを継承する必要がありました

class MyPostAdmin(admin.ModelAdmin):
    def queryset(self, request):
        return self.model.objects.filter(id=1)
3
zzart