Più amministratori / visualizzazioni Model per lo stesso modello nell'amministratore Django


150

Come posso creare più ModelAdmin per lo stesso modello, ognuno personalizzato in modo diverso e collegato a URL diversi?

Diciamo che ho un modello Django chiamato Posts. Per impostazione predefinita, la vista dell'amministratore di questo modello elencherà tutti gli oggetti Post.

So di poter personalizzare l'elenco di oggetti visualizzati sulla pagina in vari modi impostando variabili come list_display o sovrascrivendo il querysetmetodo nel mio ModelAdmin in questo modo:

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)

Per impostazione predefinita, questo sarebbe accessibile all'URL /admin/myapp/post. Tuttavia, vorrei avere più viste / ModelAdmins dello stesso modello. ad esempio /admin/myapp/post, elenca tutti gli oggetti dei post e /admin/myapp/mypostselenca tutti i post appartenenti all'utente e /admin/myapp/draftpostpuò elencare tutti i post che non sono stati ancora pubblicati. (questi sono solo esempi, il mio caso d'uso reale è più complesso)

Non è possibile registrare più di un ModelAdmin per lo stesso modello (ciò comporta AlreadyRegisteredun'eccezione). Idealmente, vorrei raggiungere questo obiettivo senza mettere tutto in una singola classe ModelAdmin e scrivere la mia funzione "urls" per restituire un set di query diverso a seconda dell'URL.

Ho dato un'occhiata alla fonte Django e vedo che funzioni del genere ModelAdmin.changelist_viewpotrebbero essere in qualche modo incluse nel mio urls.py, ma non sono sicuro di come funzionerebbe.

Aggiornamento : ho trovato un modo per fare ciò che voglio (vedi sotto), ma mi piacerebbe comunque sentire altri modi per farlo.

Risposte:


276

Ho trovato un modo per ottenere ciò che volevo, usando i modelli proxy per aggirare il fatto che ogni modello può essere registrato solo una volta.

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)

Quindi il valore predefinito PostAdminsarebbe accessibile all'indirizzo /admin/myapp/poste l'elenco dei post di proprietà dell'utente sarebbe all'indirizzo /admin/myapp/myposts.

Dopo aver visto http://code.djangoproject.com/wiki/DynamicModels , ho ideato la seguente funzione di utilità per fare la stessa cosa:

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

Questo può essere usato come segue:

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
Questo e spettacolare. non sapevo che un modello proxy potesse essere registrato nel sito di amministrazione. questo mi aiuterà molto.
Brandon Henry,

8
Avevo anche bisogno di registrare gli stessi modelli due volte in django admin e i modelli proxy sembrano funzionare. Ma ho riscontrato un problema con il sistema di autorizzazione. Vedi qui: code.djangoproject.com/ticket/11154
bjunix

4
È anche una buona idea cambiare il gestore predefinito invece del queryset ModelAdmin. Quindi il comportamento del modello proxy è coerente anche al di fuori dell'amministratore.
bjunix,

4
Ora la vera risposta è: perché Django non ti consente di avere due amministratori per lo stesso modello? non dovremmo aver bisogno di hackerare le cose per solo 2 righe che lo controllano e generano un errore: s. Ottima risposta ancora!
Hassek,

1
@zzart: c'è una richiesta pull in sospeso, che sembra essere solo documenti mancanti: github.com/django/django/pull/146/files
blueyed

3

La risposta di Paul Stone è assolutamente fantastica! Solo per aggiungere, per Django 1.4.5 avevo bisogno di ereditare la mia classe personalizzata daadmin.ModelAdmin

class MyPostAdmin(admin.ModelAdmin):
    def queryset(self, request):
        return self.model.objects.filter(id=1)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.