Django – specify which model manager Django admin should use

Question:

I’ve created a custom Manager for a Django model which returns a QuerySet holding a subset of objects.all(). I need this to be the model’s default Manager, since I am also creating a custom tag which will retrieve content from any model (specified by an argument), and needs to use the default Manager for the specified model. All that works fine, except – Django Admin is ALSO using the default Manager for this particular model, which means that not all model instances appear in the admin.

The Django docs don’t help:

If you use custom Manager objects, take note that the first Manager Django encounters (in
the order in which they’re defined in the model) has a special status. Django interprets this first Manager defined in a class as the “default” Manager, and several parts of Django (though not the admin application) will use that Manager exclusively for that model.
(Django Managers documentation)

The admin isn’t supposed to use the default Manager, but it seems to be in my case. Note that I have also explicitly add the default Manager objects:

subset = CustomManager() # the default manager
objects = models.Manager() # the one I want admin to use

How can I specify which Manager the admin should use?

Asked By: Chris Lawlor

||

Answers:

You can choose the manager by overriding the queryset method in your ModelAdmin subclass.

def get_queryset(self, request):
    # use our manager, rather than the default one
    qs = self.model.objects.get_queryset()

    # we need this from the superclass method
    ordering = self.ordering or () # otherwise we might try to *None, which is bad ;)
    if ordering:
        qs = qs.order_by(*ordering)
    return qs
Answered By: Daniel Roseman

Updated code:

def get_queryset(self, request):
    """
    Returns a QuerySet of all model instances that can be edited by the
    admin site. This is used by changelist_view.
    """
    qs = self.model._default_manager.get_queryset()
    # TODO: this should be handled by some parameter to the ChangeList.
    ordering = self.get_ordering(request)
    if ordering:
        qs = qs.order_by(*ordering)
    return qs

_default_manager can be replaced…

As we expect objects to be the sole manager, the admin will use manager in self.Admin.manager.

From the ticket https://code.djangoproject.com/ticket/4754 opened by troy.simpson

class filterManager(models.Manager):
  def get_query_set(self):
    return super(filterManager, self).get_query_set().filter(name='troy')

class Blah(models.Model):
  name = models.CharField(maxlength=100)
  objects = filterManager()
  class Admin:
    manager = filterManager()

Tested with Django 1.11

Answered By: Victor T

The order in which you define your managers matters. Admin takes the first manager defined on the model.

So if you do like this:

subset = CustomManager() # the default manager
objects = models.Manager() # the one I want admin to use

the default manager will be subset

and if you do like this:

objects = models.Manager() # the default manager
subset = CustomManager() # your own manager

then the default manager will be objects.

Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.