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.
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)
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)