~6 min read • Updated Mar 10, 2026
1. What Is a Manager?
A Manager is the interface Django uses to perform database queries. Every model automatically gets at least one Manager. By default, this Manager is named objects.
Managers are responsible for:
- Creating QuerySets
- Providing table-level operations
- Customizing default query behavior
2. Renaming the Default Manager
If you want to use a different name instead of objects, simply define a Manager attribute on the model:
class Person(models.Model):
people = models.Manager()
Now Person.objects raises an error, but Person.people.all() works normally.
3. Creating Custom Managers
You can extend models.Manager to add custom methods or modify the default QuerySet.
3.1 Adding Custom Manager Methods
Custom Manager methods are ideal for table-level logic.
class PollManager(models.Manager):
def with_counts(self):
return self.annotate(num_responses=Coalesce(models.Count("response"), 0))
Usage:
OpinionPoll.objects.with_counts()
Manager methods can return anything—not just QuerySets.
3.2 Overriding get_queryset()
To change the default QuerySet returned by a Manager, override get_queryset():
class DahlBookManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(author="Roald Dahl")
Attach it to a model:
class Book(models.Model):
objects = models.Manager()
dahl_objects = DahlBookManager()
Now:
Book.objects.all()→ all booksBook.dahl_objects.all()→ only Roald Dahl books
4. Using Multiple Managers
You can attach multiple managers to a model to create reusable filtered views:
class AuthorManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(role="A")
class EditorManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(role="E")
Attach them:
class Person(models.Model):
people = models.Manager()
authors = AuthorManager()
editors = EditorManager()
Now you can call:
Person.authors.all()Person.editors.all()Person.people.all()
5. Default Managers
The first Manager defined in a model becomes the default manager:
Model._default_manager
Django uses this manager in many internal operations (e.g., dumpdata).
You can explicitly set it using:
class Meta:
default_manager_name = "my_manager"
6. Base Managers
The base manager (_base_manager) is used when Django needs to bypass filtering—especially when retrieving related objects.
If you override the base manager using:
class Meta:
base_manager_name = "my_base_manager"
Important: A base manager must NOT filter out rows. Django relies on it to retrieve all related objects.
7. Managers and Related Object Access
When accessing related objects (e.g., choice.question), Django uses the base manager of the related model, not the default manager.
This ensures that even filtered-out objects can still be retrieved when needed.
8. Exposing Custom QuerySet Methods Through a Manager
If you define custom QuerySet methods, you must also expose them through the Manager:
class PersonQuerySet(models.QuerySet):
def authors(self):
return self.filter(role="A")
class PersonManager(models.Manager):
def get_queryset(self):
return PersonQuerySet(self.model, using=self._db)
def authors(self):
return self.get_queryset().authors()
Now:
Person.people.authors()
Conclusion
Django Managers are a powerful tool for customizing how models interact with the database. You can rename them, extend them, override their QuerySets, define multiple managers, and expose custom QuerySet logic. Understanding default and base managers is essential for avoiding unexpected behavior—especially when dealing with related objects.
1. Creating a Manager with QuerySet Methods
Instead of duplicating QuerySet methods inside a Manager, Django provides QuerySet.as_manager(), which creates a Manager that automatically exposes appropriate QuerySet methods.
Example:
class Person(models.Model):
...
people = PersonQuerySet.as_manager()
The resulting Manager behaves almost exactly like a manually written custom Manager.
Which methods get copied?
- Public methods → copied by default.
- Private methods (starting with _) → not copied.
- Methods with
queryset_only = False→ always copied. - Methods with
queryset_only = True→ never copied.
Example:
class CustomQuerySet(models.QuerySet):
def public_method(self):
return # available on Manager + QuerySet
def _private_method(self):
return # QuerySet only
def opted_out_public_method(self):
return
opted_out_public_method.queryset_only = True # QuerySet only
def _opted_in_private_method(self):
return
_opted_in_private_method.queryset_only = False # copied to Manager
2. Using from_queryset() for Advanced Manager + QuerySet Combinations
If you want both a custom Manager and a custom QuerySet, use Manager.from_queryset(). It returns a Manager subclass that includes all appropriate QuerySet methods.
Example:
class CustomManager(models.Manager):
def manager_only_method(self):
return
class CustomQuerySet(models.QuerySet):
def manager_and_queryset_method(self):
return
class MyModel(models.Model):
objects = CustomManager.from_queryset(CustomQuerySet)()
You can also store the generated class:
MyManager = CustomManager.from_queryset(CustomQuerySet)
class MyModel(models.Model):
objects = MyManager()
3. Custom Managers and Model Inheritance
Rules Django follows:
- Managers from parent classes are inherited normally.
- If no Manager is defined, Django automatically adds
objects. - The default Manager is:
- the one named in
Meta.default_manager_name, or - the first Manager defined on the model, or
- the default Manager of the first parent model.
- the one named in
Example with an abstract base class:
class AbstractBase(models.Model):
objects = CustomManager()
class Meta:
abstract = True
Case 1: Direct inheritance
class ChildA(AbstractBase):
pass # CustomManager is the default
Case 2: Override the default manager
class ChildB(AbstractBase):
default_manager = OtherManager()
Case 3: Add extra managers without overriding the default
Solution: use another abstract base class.
class ExtraManager(models.Model):
extra_manager = OtherManager()
class Meta:
abstract = True
class ChildC(AbstractBase, ExtraManager):
pass
Now:
- Default manager → CustomManager
- Additional manager → extra_manager
Important note:
You cannot call Manager methods on an abstract model:
AbstractBase.objects.do_something() # error
But calling them on concrete subclasses is valid.
4. Implementation Concerns
Django sometimes makes shallow copies of Manager instances. Therefore, your Manager must be copyable.
Example:
import copy
manager = MyManager()
my_copy = copy.copy(manager) # must work
If you override internal methods like __getattr__, ensure you don’t break copyability.
Conclusion
Using as_manager() and from_queryset() allows you to build powerful, DRY, and flexible Managers without duplicating code. Django’s inheritance rules give you fine control over default and additional Managers. Finally, ensuring your Manager is copyable prevents subtle bugs in Django’s internal query handling.
Written & researched by Dr. Shahin Siami