This manager (contributed by Jeff Elmore) should be attached to a base model class in a model-inheritance tree. It allows queries on that base model to return heterogenous results of the actual proper subtypes, without any additional queries.
For instance, if you have a
Place model with subclasses
Bar, you may want to query all Places:
nearby_places = Place.objects.filter(location='here')
But when you iterate over
nearby_places, you’ll get only
instances back, even for objects that are “really”
If you attach an
Place, you can just call the
select_subclasses() method on the
InheritanceManager or any
QuerySet from it, and the resulting objects will be instances of
from model_utils.managers import InheritanceManager class Place(models.Model): # ... objects = InheritanceManager() class Restaurant(Place): # ... class Bar(Place): # ... nearby_places = Place.objects.filter(location='here').select_subclasses() for place in nearby_places: # "place" will automatically be an instance of Place, Restaurant, or Bar
The database query performed will have an extra join for each subclass; if you
want to reduce the number of joins and you only need particular subclasses to
be returned as their actual type, you can pass subclass names to
select_subclasses(), much like the built-in
nearby_places = Place.objects.select_subclasses("restaurant") # restaurants will be Restaurant instances, bars will still be Place instances nearby_places = Place.objects.select_subclasses("restaurant", "bar") # all Places will be converted to Restaurant and Bar instances.
It is also possible to use the subclasses themselves as arguments to
select_subclasses, leaving it to calculate the relationship for you:
nearby_places = Place.objects.select_subclasses(Restaurant) # restaurants will be Restaurant instances, bars will still be Place instances nearby_places = Place.objects.select_subclasses(Restaurant, Bar) # all Places will be converted to Restaurant and Bar instances.
It is even possible to mix and match the two:
nearby_places = Place.objects.select_subclasses(Restaurant, "bar") # all Places will be converted to Restaurant and Bar instances.
InheritanceManager also provides a subclass-fetching alternative to the
place = Place.objects.get_subclass(id=some_id) # "place" will automatically be an instance of Place, Restaurant, or Bar
If you don’t explicitly call
InheritanceManager behaves identically to a normal
it’s safe to use as your default manager for the model.
Many custom model managers do nothing more than return a QuerySet that
is filtered in some way.
QueryManager allows you to express this
pattern with a minimum of boilerplate:
from django.db import models from model_utils.managers import QueryManager class Post(models.Model): ... published = models.BooleanField() pub_date = models.DateField() ... objects = models.Manager() public = QueryManager(published=True).order_by('-pub_date')
The kwargs passed to
QueryManager will be passed as-is to the
QuerySet.filter() method. You can also pass a
Q object to
QueryManager to express more complex conditions. Note that you can
set the ordering of the
QuerySet returned by the
by chaining a call to
.order_by() on the
QueryManager (this is
Returns only model instances that have the
is_removed field set
to False. Uses
SoftDeletableQuerySet, which ensures model instances
won’t be removed in bulk, but they will be marked as removed instead.
Each of the above manager classes has a corresponding mixin that can be used to add functionality to any manager.
Note that any manager class using
InheritanceManagerMixin must return a
QuerySet class using
InheritanceQuerySetMixin from its