Django管理员中同一模型的多个ModelAdmins /视图


149

如何为同一个模型创建一个以上的ModelAdmin,每个ModelAdmin进行不同的自定义并链接到不同的URL?

假设我有一个称为Posts的Django模型。默认情况下,此模型的admin视图将列出所有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异常)。理想情况下,我希望将所有内容放入单个ModelAdmin类中并编写自己的“ urls”函数以根据URL返回不同的查询集来实现这一点。

我看了看Django的源代码,发现ModelAdmin.changelist_view在urls.py中可以包含这样的函数,但是我不确定它是如何工作的。

更新:我找到了一种实现自己想要的方式(见下文),但是我仍然想听听其他实现方式。

Answers:


274

通过使用代理模型来解决每个模型只能注册一次的事实,我找到了一种实现我想要的方法。

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中两次注册相同的模型,并且代理模型似乎可以工作。但是我发现许可系统存在一个问题。参见此处:code.djangoproject.com/ticket/11154
bjunix 2010年

4
更改默认管理器而不是ModelAdmin查询集也是一个好主意。因此,即使在管理员外部,代理模型的行为也是一致的。
bjunix 2010年

4
现在真正的答案是,为什么django不允许您使用同一模型的两个管理员?我们只需要检查两行并抛出错误:s,就不必乱搞东西。仍然是一个很好的答案!
Hassek

1
@zzart:有一个待处理的请求,似乎丢失了文档:github.com/django/django/pull/146/files
2013年

3

保罗·斯通的回答绝对是伟大的!补充一下,对于Django 1.4.5,我需要继承自定义类admin.ModelAdmin

class MyPostAdmin(admin.ModelAdmin):
    def queryset(self, request):
        return self.model.objects.filter(id=1)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.