Django adminの同じモデルに対する複数のModelAdmins /ビュー


149

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

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

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

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

回答:


274

プロキシモデルを使用して、各モデルが一度だけ登録される可能性があるという事実を回避することによって、私が望むものを達成する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)

8
これは素晴らしいです。プロキシモデルを管理サイトに登録できることを知りませんでした。これは実際私に大いに役立ちます。
ブランドンヘンリー

8
また、同じモデルをdjango adminに2回登録する必要があり、プロキシモデルが機能しているようです。しかし、許可システムに問題が1つ見つかりました。ここを参照してください:code.djangoproject.com/ticket/11154
bjunix

4
また、ModelAdminクエリセットの代わりにデフォルトマネージャーを変更することをお勧めします。したがって、プロキシモデルの動作は、管理者以外でも一貫しています。
bjunix

4
本当の答えは、なぜdjangoでは同じモデルに対して2人の管理者を許可しないのですか?それをチェックしてエラーをスローする2行だけでハッキングする必要はないはずです:s。すばらしい回答です。
Hassek

1
@zzart:保留中のプルリクエストがあり、ドキュメントが不足しているようです:github.com/django/django/pull/146/files
blueyed '

3

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

class MyPostAdmin(admin.ModelAdmin):
    def queryset(self, request):
        return self.model.objects.filter(id=1)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.