2010-02-08 28 views
115

如何爲同一個模型創建多個ModelAdmin,每個模型都定製不同並鏈接到不同的URL?Django中的多個ModelAdmins /視圖admin

假設我有一個名爲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異常)。理想情況下,我想通過而不用將所有內容放入一個ModelAdmin類中,並編寫我自己的'urls'函數以根據URL返回不同的查詢集。

我看了一下Django的源代碼,看到可能包含在我的urls.py中的函數,如ModelAdmin.changelist_view,但我不確定這是如何工作的。

更新:我找到了一種做我想做的事情的方法(見下文),但我仍然想聽到其他方式做到這一點。

回答

214

我發現一個方法可以達到我想要的東西,通過使用代理模型來解決每個模型可以一次註冊的事實。

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

class MyPosts(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會在/管理/ MYAPP /後和用戶所擁有的將是在/管理/ 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) 
+7

這太棒了。我不知道代理模型可以在管理站點註冊。這實際上對我很有幫助。 –

+7

我還需要在django admin和代理模型中註冊兩次相同的模型。但是我發現許可系統存在一個問題。請參閱: http://code.djangoproject.com/ticket/11154 – bjunix

+4

更改默認管理器而不是ModelAdmin查詢集也是一個好主意。因此,即使在管理員之外,代理模型的行爲也是一致的。 – bjunix

1

只是使用list_filter或date_hierarchy。

date_hierarchy = 'pub_date' 

list_filter = ['pub_date',] 
+0

繼承我的自定義類「這樣算下來,分層導航,按日期,在列表頁面的頂部。在頂層,則顯示所有可用年,然後鑽到幾個月,最後幾天。「從django文檔 –

+0

按日期過濾只是一個例子,正如我在我的問題中所述。我其實需要做一個更復雜的查詢。 –

+1

好吧,這是什麼問題? –

3

保羅·斯通回答絕對好!我想補充,Django的1.4.5我需要從admin.ModelAdmin

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