1. """
    
  2. Giving models a custom manager
    
  3. 
    
  4. You can use a custom ``Manager`` in a particular model by extending the base
    
  5. ``Manager`` class and instantiating your custom ``Manager`` in your model.
    
  6. 
    
  7. There are two reasons you might want to customize a ``Manager``: to add extra
    
  8. ``Manager`` methods, and/or to modify the initial ``QuerySet`` the ``Manager``
    
  9. returns.
    
  10. """
    
  11. 
    
  12. from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
    
  13. from django.db import models
    
  14. 
    
  15. 
    
  16. class PersonManager(models.Manager):
    
  17.     def get_fun_people(self):
    
  18.         return self.filter(fun=True)
    
  19. 
    
  20. 
    
  21. class PublishedBookManager(models.Manager):
    
  22.     def get_queryset(self):
    
  23.         return super().get_queryset().filter(is_published=True)
    
  24. 
    
  25. 
    
  26. class AnnotatedBookManager(models.Manager):
    
  27.     def get_queryset(self):
    
  28.         return (
    
  29.             super()
    
  30.             .get_queryset()
    
  31.             .annotate(favorite_avg=models.Avg("favorite_books__favorite_thing_id"))
    
  32.         )
    
  33. 
    
  34. 
    
  35. class CustomQuerySet(models.QuerySet):
    
  36.     def filter(self, *args, **kwargs):
    
  37.         queryset = super().filter(fun=True)
    
  38.         queryset._filter_CustomQuerySet = True
    
  39.         return queryset
    
  40. 
    
  41.     def public_method(self, *args, **kwargs):
    
  42.         return self.all()
    
  43. 
    
  44.     def _private_method(self, *args, **kwargs):
    
  45.         return self.all()
    
  46. 
    
  47.     def optout_public_method(self, *args, **kwargs):
    
  48.         return self.all()
    
  49. 
    
  50.     optout_public_method.queryset_only = True
    
  51. 
    
  52.     def _optin_private_method(self, *args, **kwargs):
    
  53.         return self.all()
    
  54. 
    
  55.     _optin_private_method.queryset_only = False
    
  56. 
    
  57. 
    
  58. class BaseCustomManager(models.Manager):
    
  59.     def __init__(self, arg):
    
  60.         super().__init__()
    
  61.         self.init_arg = arg
    
  62. 
    
  63.     def filter(self, *args, **kwargs):
    
  64.         queryset = super().filter(fun=True)
    
  65.         queryset._filter_CustomManager = True
    
  66.         return queryset
    
  67. 
    
  68.     def manager_only(self):
    
  69.         return self.all()
    
  70. 
    
  71. 
    
  72. CustomManager = BaseCustomManager.from_queryset(CustomQuerySet)
    
  73. 
    
  74. 
    
  75. class CustomInitQuerySet(models.QuerySet):
    
  76.     # QuerySet with an __init__() method that takes an additional argument.
    
  77.     def __init__(
    
  78.         self, custom_optional_arg=None, model=None, query=None, using=None, hints=None
    
  79.     ):
    
  80.         super().__init__(model=model, query=query, using=using, hints=hints)
    
  81. 
    
  82. 
    
  83. class DeconstructibleCustomManager(BaseCustomManager.from_queryset(CustomQuerySet)):
    
  84.     def __init__(self, a, b, c=1, d=2):
    
  85.         super().__init__(a)
    
  86. 
    
  87. 
    
  88. class FunPeopleManager(models.Manager):
    
  89.     def get_queryset(self):
    
  90.         return super().get_queryset().filter(fun=True)
    
  91. 
    
  92. 
    
  93. class BoringPeopleManager(models.Manager):
    
  94.     def get_queryset(self):
    
  95.         return super().get_queryset().filter(fun=False)
    
  96. 
    
  97. 
    
  98. class Person(models.Model):
    
  99.     first_name = models.CharField(max_length=30)
    
  100.     last_name = models.CharField(max_length=30)
    
  101.     fun = models.BooleanField(default=False)
    
  102. 
    
  103.     favorite_book = models.ForeignKey(
    
  104.         "Book", models.SET_NULL, null=True, related_name="favorite_books"
    
  105.     )
    
  106.     favorite_thing_type = models.ForeignKey(
    
  107.         "contenttypes.ContentType", models.SET_NULL, null=True
    
  108.     )
    
  109.     favorite_thing_id = models.IntegerField(null=True)
    
  110.     favorite_thing = GenericForeignKey("favorite_thing_type", "favorite_thing_id")
    
  111. 
    
  112.     objects = PersonManager()
    
  113.     fun_people = FunPeopleManager()
    
  114.     boring_people = BoringPeopleManager()
    
  115. 
    
  116.     custom_queryset_default_manager = CustomQuerySet.as_manager()
    
  117.     custom_queryset_custom_manager = CustomManager("hello")
    
  118.     custom_init_queryset_manager = CustomInitQuerySet.as_manager()
    
  119. 
    
  120.     def __str__(self):
    
  121.         return "%s %s" % (self.first_name, self.last_name)
    
  122. 
    
  123. 
    
  124. class FunPerson(models.Model):
    
  125.     first_name = models.CharField(max_length=30)
    
  126.     last_name = models.CharField(max_length=30)
    
  127.     fun = models.BooleanField(default=True)
    
  128.     favorite_book = models.ForeignKey(
    
  129.         "Book",
    
  130.         models.SET_NULL,
    
  131.         null=True,
    
  132.         related_name="fun_people_favorite_books",
    
  133.     )
    
  134.     favorite_thing_type = models.ForeignKey(
    
  135.         "contenttypes.ContentType", models.SET_NULL, null=True
    
  136.     )
    
  137.     favorite_thing_id = models.IntegerField(null=True)
    
  138.     favorite_thing = GenericForeignKey("favorite_thing_type", "favorite_thing_id")
    
  139. 
    
  140.     objects = FunPeopleManager()
    
  141. 
    
  142. 
    
  143. class Book(models.Model):
    
  144.     title = models.CharField(max_length=50)
    
  145.     author = models.CharField(max_length=30)
    
  146.     is_published = models.BooleanField(default=False)
    
  147.     authors = models.ManyToManyField(Person, related_name="books")
    
  148.     fun_authors = models.ManyToManyField(FunPerson, related_name="books")
    
  149.     favorite_things = GenericRelation(
    
  150.         Person,
    
  151.         content_type_field="favorite_thing_type",
    
  152.         object_id_field="favorite_thing_id",
    
  153.     )
    
  154.     fun_people_favorite_things = GenericRelation(
    
  155.         FunPerson,
    
  156.         content_type_field="favorite_thing_type",
    
  157.         object_id_field="favorite_thing_id",
    
  158.     )
    
  159. 
    
  160.     published_objects = PublishedBookManager()
    
  161.     annotated_objects = AnnotatedBookManager()
    
  162. 
    
  163.     class Meta:
    
  164.         base_manager_name = "annotated_objects"
    
  165. 
    
  166. 
    
  167. class FastCarManager(models.Manager):
    
  168.     def get_queryset(self):
    
  169.         return super().get_queryset().filter(top_speed__gt=150)
    
  170. 
    
  171. 
    
  172. class Car(models.Model):
    
  173.     name = models.CharField(max_length=10)
    
  174.     mileage = models.IntegerField()
    
  175.     top_speed = models.IntegerField(help_text="In miles per hour.")
    
  176.     cars = models.Manager()
    
  177.     fast_cars = FastCarManager()
    
  178. 
    
  179. 
    
  180. class FastCarAsBase(Car):
    
  181.     class Meta:
    
  182.         proxy = True
    
  183.         base_manager_name = "fast_cars"
    
  184. 
    
  185. 
    
  186. class FastCarAsDefault(Car):
    
  187.     class Meta:
    
  188.         proxy = True
    
  189.         default_manager_name = "fast_cars"
    
  190. 
    
  191. 
    
  192. class RestrictedManager(models.Manager):
    
  193.     def get_queryset(self):
    
  194.         return super().get_queryset().filter(is_public=True)
    
  195. 
    
  196. 
    
  197. class RelatedModel(models.Model):
    
  198.     name = models.CharField(max_length=50)
    
  199. 
    
  200. 
    
  201. class RestrictedModel(models.Model):
    
  202.     name = models.CharField(max_length=50)
    
  203.     is_public = models.BooleanField(default=False)
    
  204.     related = models.ForeignKey(RelatedModel, models.CASCADE)
    
  205. 
    
  206.     objects = RestrictedManager()
    
  207.     plain_manager = models.Manager()
    
  208. 
    
  209. 
    
  210. class OneToOneRestrictedModel(models.Model):
    
  211.     name = models.CharField(max_length=50)
    
  212.     is_public = models.BooleanField(default=False)
    
  213.     related = models.OneToOneField(RelatedModel, models.CASCADE)
    
  214. 
    
  215.     objects = RestrictedManager()
    
  216.     plain_manager = models.Manager()
    
  217. 
    
  218. 
    
  219. class AbstractPerson(models.Model):
    
  220.     abstract_persons = models.Manager()
    
  221.     objects = models.CharField(max_length=30)
    
  222. 
    
  223.     class Meta:
    
  224.         abstract = True
    
  225. 
    
  226. 
    
  227. class PersonFromAbstract(AbstractPerson):
    
  228.     pass