Multiple ModelAdmins/views for same model in Django admin

Hi,
I am looking for a way to display multiple list in the administration nav bar where all of these list will be named differently and show the same model with differents query_set.

I have tried many ways found on the internet but these solutions are 10 years old and doesn’t work anymore

Thanks for your help

You can show the same model multiple times in the admin by creating Proxy models.

You can create a Proxy model for an existing model, and then create a ModelAdmin for that Proxy.

Thanks [KenWhitesell].
I’m sorry English is not my native language I corrected the bad wording, hope you will understand me better.
I have tried this solution before but it doesn’t work.

model.py

class Photo(models.Model):
    class Meta:
        verbose_name_plural = "des photos"
        verbose_name = "une photo"

    nom = models.CharField(max_length=30)
    categorie = models.ForeignKey(CategoriePhoto, on_delete=models.CASCADE, null=True, blank=True)
    fichier = models.ImageField(upload_to='images_prestations/', verbose_name='photo')
    mariage = models.BooleanField()

    def __str__(self):
        """retourne un object lisible"""
        return self.nom


class PhotoMariage(Photo):
    class Meta:
        proxy = True
        verbose_name = "photo de mariage"

admin.py

class PhotoMariageAdmin(admin.ModelAdmin):

    def changelist_view(self, request, extra_context=None):
        extra_context = {'title': 'Sélectionnez la photo à changer'}
        return super(PhotoMariageAdmin, self).changelist_view(request, extra_context=extra_context)

    def add_view(self, request, object_id=None, form_url='', extra_context=None):
        extra_context = {'title': 'Ajout d\'une photo'}
        return super().add_view(request, extra_context=extra_context)

    def change_view(self, request, object_id, form_url='', extra_context=None):
        extra_context = {'title': 'Modification d\'une photo'}
        return super().change_view(request, object_id, form_url, extra_context=extra_context)

    # j'utilise get_queryset pour modifier ce qui est affiché dans la liste,
    # ici je n'affiche que les photos de mariage
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.filter(mariage=True)


admin.site.register(PhotoMariage, PhotoMariageAdmin)

When you say “it doesn’t work”, what exactly is happening that isn’t working? What are you expecting to have happen, and what’s failing?

(Note, most ModelAdmin customizations are done through the parameters, not by overriding methods.)

Can you give me an exemple please ?
For exemple Instead of override changelist_view i can do the same thing in other way ?

I expect Django add a link of list_view in the nav bar for my proxy class like it do it for regular class registered

More precisely i want to have several list in the navbar that shows the same model with different query set and verbose_name

And what are you getting or not getting with your attempt above? (Is it showing up in the Admin menu? Or is it showing up but not showing the different queryset?)

I can ask django for add list_view link in navbar for a model like that :
admin.py
admin.site.register(Model, MyModelAdmin)

But django doesn’t do nothing if i use proxy class like that :
admin.py
admin.site.register(MyProxyClass,MyModelAADminForProxyClass)

There is no error, django just do nothing, my second view don’t appear in the navbar

This works fine for me. That implies that there’s something else going wrong here.

Start with the simple case, remove everything from the Proxy ModelAdmin class so that it’s just:

class PhotoMariageAdmin(admin.ModelAdmin):
    pass

We may need to dig more deeply into your configuration and environment:

  • What version of Django are you using?
  • What version of Python are you using?
  • What third-party packages do you have installed in your Django virtual environment?
  • Are you using a customized or third-party admin package?

Endeed I just made an empty test project and it works

model.py

from django.db import models

class Photo(models.Model):
    nom = models.CharField(max_length=30)
    mariage = models.BooleanField()

    def __str__(self):
        """retourne un object lisible"""
        return self.nom


class PhotoMariage(Photo):
    class Meta:
        proxy = True
        verbose_name = "photo de mariage"

admin.py

from django.contrib import admin
from .models import Photo, PhotoMariage


class PhotoAdmin(admin.ModelAdmin):
    list_display = ('nom', 'mariage')

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.filter(mariage=False)


class PhotoMariageAdmin(admin.ModelAdmin):
    list_display = ('nom', 'mariage')

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.filter(mariage=True)


admin.site.register(Photo, PhotoAdmin)
admin.site.register(PhotoMariage, PhotoMariageAdmin)

And the result in the backend

photo de mariage
photo

For you’r questions
Django 3.2.1
Python 3.7.4
I don’t use third-party packages
I don’t use costomized third party admin package

Now i just need to understand what i have done who break the backend :wink:
Thanks a lot for your help,

I’m really disappointed, after my precedent test i have try again on my project and now it work but i’m unable to determine what i have changed…

Really, Thank you for being there with your time.

Before you tell me :

(Note, most ModelAdmin customizations are done through the parameters, not by overriding methods.)

This way is not correct ?

class PhotoMariageAdmin(admin.ModelAdmin):

    def changelist_view(self, request, extra_context=None):
        extra_context = {'title': 'Sélectionnez la photo de mariage à changer'}
        return super(PhotoMariageAdmin, self).changelist_view(request, extra_context=extra_context)

    def add_view(self, request, object_id=None, form_url='', extra_context=None):
        extra_context = {'title': 'Ajout d\'une photo de mariage'}
        return super().add_view(request, extra_context=extra_context)

    def change_view(self, request, object_id, form_url='', extra_context=None):
        extra_context = {'title': 'Modification d\'une photo de mariage'}
        return super().change_view(request, object_id, form_url, extra_context=extra_context)

Have a good day

It depends upon what exactly you’re trying to do. This may or may not be the most appropriate way to do “something”, but it really depends upon what that “something” is. I can’t tell from this snippet what your real objective is.

I understand now !
When i was comeback to my project i was login with superuser account…
The problem was that before I was using a user account that did not have permission to see my new proxy class
So much time spend for nothing…
I’m really sorry to have bothered you for so little, it might be useful for other people who would make the same mistake