web-dev-qa-db-fra.com

Plusieurs administrateurs de modèle / vues pour le même modèle dans Django admin

Comment puis-je créer plus d'un ModelAdmin pour le même modèle, chacun personnalisé différemment et lié à différentes URL?

Disons que j'ai un modèle Django appelé Posts. Par défaut, la vue d'administration de ce modèle listera tous les objets Post.

Je sais que je peux personnaliser la liste des objets affichés sur la page de différentes manières en définissant des variables comme list_display ou en remplaçant la méthode queryset dans mon ModelAdmin comme ceci:

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)

Par défaut, cela serait accessible à l'URL /admin/myapp/post. Cependant, j'aimerais avoir plusieurs vues/ModelAdmins du même modèle. par exemple /admin/myapp/post répertorierait tous les objets de publication et /admin/myapp/myposts répertorierait tous les messages appartenant à l'utilisateur, et /admin/myapp/draftpost peut répertorier tous les messages qui n'ont pas encore été publiés. (ce ne sont que des exemples, mon cas d'utilisation réel est plus complexe)

Vous ne pouvez pas enregistrer plusieurs ModelAdmin pour le même modèle (cela entraîne une exception AlreadyRegistered). Idéalement, j'aimerais y parvenir sans tout mettre dans une seule classe ModelAdmin et écrire ma propre fonction 'urls' pour retourner un ensemble de requêtes différent en fonction de l'URL.

J'ai jeté un œil à la source Django et je vois des fonctions comme ModelAdmin.changelist_view qui pourrait être en quelque sorte inclus dans mon urls.py, mais je ne sais pas exactement comment cela fonctionnerait.

Mise à jour: J'ai trouvé une façon de faire ce que je veux (voir ci-dessous), mais j'aimerais encore entendre d'autres façons de le faire.

142
Paul Stone

J'ai trouvé un moyen d'atteindre ce que je veux, en utilisant des modèles proxy pour contourner le fait que chaque modèle ne peut être enregistré qu'une seule fois.

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)

Le PostAdmin par défaut serait alors accessible à /admin/myapp/post et la liste des publications appartenant à l'utilisateur serait à /admin/myapp/myposts.

Après avoir regardé http://code.djangoproject.com/wiki/DynamicModels , j'ai trouvé la fonction utilitaire de fonction suivante pour faire la même chose:

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

Cela peut être utilisé comme suit:

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

La réponse de Paul Stone est absolument géniale! Juste pour ajouter, pour Django 1.4.5 j'avais besoin d'hériter ma classe personnalisée de admin.ModelAdmin

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