Vários ModelAdmins / views para o mesmo modelo no Django admin


149

Como posso criar mais de um ModelAdmin para o mesmo modelo, cada um personalizado de forma diferente e vinculado a URLs diferentes?

Digamos que eu tenho um modelo do Django chamado Posts. Por padrão, a visualização de administrador deste modelo listará todos os objetos de postagem.

Eu sei que posso personalizar a lista de objetos exibidos na página de várias maneiras, definindo variáveis ​​como list_display ou substituindo o querysetmétodo no meu ModelAdmin da seguinte maneira:

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)

Por padrão, isso estaria acessível no URL /admin/myapp/post. No entanto, eu gostaria de ter várias visualizações / ModelAdmins do mesmo modelo. por exemplo /admin/myapp/post, listaria todos os objetos de postagem e /admin/myapp/mypostslistaria todas as postagens pertencentes ao usuário e /admin/myapp/draftpostpode listar todas as postagens que ainda não foram publicadas. (estes são apenas exemplos, meu caso de uso real é mais complexo)

Você não pode registrar mais de um ModelAdmin para o mesmo modelo (isso resulta em uma AlreadyRegisteredexceção). Idealmente, eu gostaria de conseguir isso sem colocar tudo em uma única classe ModelAdmin e escrever minha própria função 'urls' para retornar um conjunto de consultas diferente, dependendo da URL.

Eu dei uma olhada na fonte do Django e vejo funções como ModelAdmin.changelist_viewessa que de alguma forma podem ser incluídas no meu urls.py, mas não tenho certeza exatamente como isso funcionaria.

Atualização : Encontrei uma maneira de fazer o que quero (veja abaixo), mas ainda gostaria de ouvir outras maneiras de fazer isso.

Respostas:


274

Encontrei uma maneira de conseguir o que quero, usando modelos de proxy para contornar o fato de que cada modelo pode ser registrado apenas uma vez.

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)

Em seguida, o padrão PostAdminestará acessível em /admin/myapp/poste a lista de postagens pertencentes ao usuário estará em /admin/myapp/myposts.

Depois de examinar http://code.djangoproject.com/wiki/DynamicModels , criei a seguinte função utilitário de função para fazer a mesma coisa:

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

Isso pode ser usado da seguinte maneira:

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
isso é incrível. eu não sabia que um modelo de proxy poderia ser registrado no site de administração. isso realmente vai me ajudar muito.
Brandon Henry

8
Eu também precisei registrar os mesmos modelos duas vezes no django admin e os modelos de proxy parecem funcionar. Mas eu encontrei um problema com o sistema de permissão. Veja aqui: code.djangoproject.com/ticket/11154
bjunix

4
Também é uma boa ideia alterar o gerenciador padrão em vez do conjunto de consultas ModelAdmin. Portanto, o comportamento do modelo de proxy é consistente mesmo fora do administrador.
bjunix

4
Agora, a verdadeira resposta é: por que o django não permite que você tenha dois administradores para o mesmo modelo? não devemos precisar desviar das coisas por apenas duas linhas que verificam isso e geram um erro: s. Ótima resposta ainda!
Hassek 4/11/11

1
@zzart: existe uma solicitação de recebimento pendente, que parece estar faltando docs: github.com/django/django/pull/146/files
rededed

3

A resposta de Paul Stone é absolutamente ótima! Apenas para adicionar, para o Django 1.4.5 eu precisava herdar minha classe personalizada deadmin.ModelAdmin

class MyPostAdmin(admin.ModelAdmin):
    def queryset(self, request):
        return self.model.objects.filter(id=1)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.