1. from django.db import models
    
  2. from django.test import TestCase
    
  3. 
    
  4. from .models import (
    
  5.     Book,
    
  6.     Car,
    
  7.     CustomManager,
    
  8.     CustomQuerySet,
    
  9.     DeconstructibleCustomManager,
    
  10.     FastCarAsBase,
    
  11.     FastCarAsDefault,
    
  12.     FunPerson,
    
  13.     OneToOneRestrictedModel,
    
  14.     Person,
    
  15.     PersonFromAbstract,
    
  16.     PersonManager,
    
  17.     PublishedBookManager,
    
  18.     RelatedModel,
    
  19.     RestrictedModel,
    
  20. )
    
  21. 
    
  22. 
    
  23. class CustomManagerTests(TestCase):
    
  24.     custom_manager_names = [
    
  25.         "custom_queryset_default_manager",
    
  26.         "custom_queryset_custom_manager",
    
  27.     ]
    
  28. 
    
  29.     @classmethod
    
  30.     def setUpTestData(cls):
    
  31.         cls.b1 = Book.published_objects.create(
    
  32.             title="How to program", author="Rodney Dangerfield", is_published=True
    
  33.         )
    
  34.         cls.b2 = Book.published_objects.create(
    
  35.             title="How to be smart", author="Albert Einstein", is_published=False
    
  36.         )
    
  37. 
    
  38.         cls.p1 = Person.objects.create(first_name="Bugs", last_name="Bunny", fun=True)
    
  39.         cls.droopy = Person.objects.create(
    
  40.             first_name="Droopy", last_name="Dog", fun=False
    
  41.         )
    
  42. 
    
  43.     def test_custom_manager_basic(self):
    
  44.         """
    
  45.         Test a custom Manager method.
    
  46.         """
    
  47.         self.assertQuerysetEqual(Person.objects.get_fun_people(), ["Bugs Bunny"], str)
    
  48. 
    
  49.     def test_queryset_copied_to_default(self):
    
  50.         """
    
  51.         The methods of a custom QuerySet are properly copied onto the
    
  52.         default Manager.
    
  53.         """
    
  54.         for manager_name in self.custom_manager_names:
    
  55.             with self.subTest(manager_name=manager_name):
    
  56.                 manager = getattr(Person, manager_name)
    
  57. 
    
  58.                 # Public methods are copied
    
  59.                 manager.public_method()
    
  60.                 # Private methods are not copied
    
  61.                 with self.assertRaises(AttributeError):
    
  62.                     manager._private_method()
    
  63. 
    
  64.     def test_manager_honors_queryset_only(self):
    
  65.         for manager_name in self.custom_manager_names:
    
  66.             with self.subTest(manager_name=manager_name):
    
  67.                 manager = getattr(Person, manager_name)
    
  68.                 # Methods with queryset_only=False are copied even if they are private.
    
  69.                 manager._optin_private_method()
    
  70.                 # Methods with queryset_only=True aren't copied even if they are public.
    
  71.                 msg = (
    
  72.                     "%r object has no attribute 'optout_public_method'"
    
  73.                     % manager.__class__.__name__
    
  74.                 )
    
  75.                 with self.assertRaisesMessage(AttributeError, msg):
    
  76.                     manager.optout_public_method()
    
  77. 
    
  78.     def test_manager_use_queryset_methods(self):
    
  79.         """
    
  80.         Custom manager will use the queryset methods
    
  81.         """
    
  82.         for manager_name in self.custom_manager_names:
    
  83.             with self.subTest(manager_name=manager_name):
    
  84.                 manager = getattr(Person, manager_name)
    
  85.                 queryset = manager.filter()
    
  86.                 self.assertQuerysetEqual(queryset, ["Bugs Bunny"], str)
    
  87.                 self.assertIs(queryset._filter_CustomQuerySet, True)
    
  88. 
    
  89.                 # Specialized querysets inherit from our custom queryset.
    
  90.                 queryset = manager.values_list("first_name", flat=True).filter()
    
  91.                 self.assertEqual(list(queryset), ["Bugs"])
    
  92.                 self.assertIs(queryset._filter_CustomQuerySet, True)
    
  93. 
    
  94.                 self.assertIsInstance(queryset.values(), CustomQuerySet)
    
  95.                 self.assertIsInstance(queryset.values().values(), CustomQuerySet)
    
  96.                 self.assertIsInstance(queryset.values_list().values(), CustomQuerySet)
    
  97. 
    
  98.     def test_init_args(self):
    
  99.         """
    
  100.         The custom manager __init__() argument has been set.
    
  101.         """
    
  102.         self.assertEqual(Person.custom_queryset_custom_manager.init_arg, "hello")
    
  103. 
    
  104.     def test_manager_attributes(self):
    
  105.         """
    
  106.         Custom manager method is only available on the manager and not on
    
  107.         querysets.
    
  108.         """
    
  109.         Person.custom_queryset_custom_manager.manager_only()
    
  110.         msg = "'CustomQuerySet' object has no attribute 'manager_only'"
    
  111.         with self.assertRaisesMessage(AttributeError, msg):
    
  112.             Person.custom_queryset_custom_manager.all().manager_only()
    
  113. 
    
  114.     def test_queryset_and_manager(self):
    
  115.         """
    
  116.         Queryset method doesn't override the custom manager method.
    
  117.         """
    
  118.         queryset = Person.custom_queryset_custom_manager.filter()
    
  119.         self.assertQuerysetEqual(queryset, ["Bugs Bunny"], str)
    
  120.         self.assertIs(queryset._filter_CustomManager, True)
    
  121. 
    
  122.     def test_related_manager(self):
    
  123.         """
    
  124.         The related managers extend the default manager.
    
  125.         """
    
  126.         self.assertIsInstance(self.droopy.books, PublishedBookManager)
    
  127.         self.assertIsInstance(self.b2.authors, PersonManager)
    
  128. 
    
  129.     def test_no_objects(self):
    
  130.         """
    
  131.         The default manager, "objects", doesn't exist, because a custom one
    
  132.         was provided.
    
  133.         """
    
  134.         msg = "type object 'Book' has no attribute 'objects'"
    
  135.         with self.assertRaisesMessage(AttributeError, msg):
    
  136.             Book.objects
    
  137. 
    
  138.     def test_filtering(self):
    
  139.         """
    
  140.         Custom managers respond to usual filtering methods
    
  141.         """
    
  142.         self.assertQuerysetEqual(
    
  143.             Book.published_objects.all(),
    
  144.             [
    
  145.                 "How to program",
    
  146.             ],
    
  147.             lambda b: b.title,
    
  148.         )
    
  149. 
    
  150.     def test_fk_related_manager(self):
    
  151.         Person.objects.create(
    
  152.             first_name="Bugs", last_name="Bunny", fun=True, favorite_book=self.b1
    
  153.         )
    
  154.         Person.objects.create(
    
  155.             first_name="Droopy", last_name="Dog", fun=False, favorite_book=self.b1
    
  156.         )
    
  157.         FunPerson.objects.create(
    
  158.             first_name="Bugs", last_name="Bunny", fun=True, favorite_book=self.b1
    
  159.         )
    
  160.         FunPerson.objects.create(
    
  161.             first_name="Droopy", last_name="Dog", fun=False, favorite_book=self.b1
    
  162.         )
    
  163. 
    
  164.         self.assertQuerysetEqual(
    
  165.             self.b1.favorite_books.order_by("first_name").all(),
    
  166.             [
    
  167.                 "Bugs",
    
  168.                 "Droopy",
    
  169.             ],
    
  170.             lambda c: c.first_name,
    
  171.             ordered=False,
    
  172.         )
    
  173.         self.assertQuerysetEqual(
    
  174.             self.b1.fun_people_favorite_books.all(),
    
  175.             [
    
  176.                 "Bugs",
    
  177.             ],
    
  178.             lambda c: c.first_name,
    
  179.             ordered=False,
    
  180.         )
    
  181.         self.assertQuerysetEqual(
    
  182.             self.b1.favorite_books(manager="boring_people").all(),
    
  183.             [
    
  184.                 "Droopy",
    
  185.             ],
    
  186.             lambda c: c.first_name,
    
  187.             ordered=False,
    
  188.         )
    
  189.         self.assertQuerysetEqual(
    
  190.             self.b1.favorite_books(manager="fun_people").all(),
    
  191.             [
    
  192.                 "Bugs",
    
  193.             ],
    
  194.             lambda c: c.first_name,
    
  195.             ordered=False,
    
  196.         )
    
  197. 
    
  198.     def test_gfk_related_manager(self):
    
  199.         Person.objects.create(
    
  200.             first_name="Bugs", last_name="Bunny", fun=True, favorite_thing=self.b1
    
  201.         )
    
  202.         Person.objects.create(
    
  203.             first_name="Droopy", last_name="Dog", fun=False, favorite_thing=self.b1
    
  204.         )
    
  205.         FunPerson.objects.create(
    
  206.             first_name="Bugs", last_name="Bunny", fun=True, favorite_thing=self.b1
    
  207.         )
    
  208.         FunPerson.objects.create(
    
  209.             first_name="Droopy", last_name="Dog", fun=False, favorite_thing=self.b1
    
  210.         )
    
  211. 
    
  212.         self.assertQuerysetEqual(
    
  213.             self.b1.favorite_things.all(),
    
  214.             [
    
  215.                 "Bugs",
    
  216.                 "Droopy",
    
  217.             ],
    
  218.             lambda c: c.first_name,
    
  219.             ordered=False,
    
  220.         )
    
  221.         self.assertQuerysetEqual(
    
  222.             self.b1.fun_people_favorite_things.all(),
    
  223.             [
    
  224.                 "Bugs",
    
  225.             ],
    
  226.             lambda c: c.first_name,
    
  227.             ordered=False,
    
  228.         )
    
  229.         self.assertQuerysetEqual(
    
  230.             self.b1.favorite_things(manager="boring_people").all(),
    
  231.             [
    
  232.                 "Droopy",
    
  233.             ],
    
  234.             lambda c: c.first_name,
    
  235.             ordered=False,
    
  236.         )
    
  237.         self.assertQuerysetEqual(
    
  238.             self.b1.favorite_things(manager="fun_people").all(),
    
  239.             [
    
  240.                 "Bugs",
    
  241.             ],
    
  242.             lambda c: c.first_name,
    
  243.             ordered=False,
    
  244.         )
    
  245. 
    
  246.     def test_m2m_related_manager(self):
    
  247.         bugs = Person.objects.create(first_name="Bugs", last_name="Bunny", fun=True)
    
  248.         self.b1.authors.add(bugs)
    
  249.         droopy = Person.objects.create(first_name="Droopy", last_name="Dog", fun=False)
    
  250.         self.b1.authors.add(droopy)
    
  251.         bugs = FunPerson.objects.create(first_name="Bugs", last_name="Bunny", fun=True)
    
  252.         self.b1.fun_authors.add(bugs)
    
  253.         droopy = FunPerson.objects.create(
    
  254.             first_name="Droopy", last_name="Dog", fun=False
    
  255.         )
    
  256.         self.b1.fun_authors.add(droopy)
    
  257. 
    
  258.         self.assertQuerysetEqual(
    
  259.             self.b1.authors.order_by("first_name").all(),
    
  260.             [
    
  261.                 "Bugs",
    
  262.                 "Droopy",
    
  263.             ],
    
  264.             lambda c: c.first_name,
    
  265.             ordered=False,
    
  266.         )
    
  267.         self.assertQuerysetEqual(
    
  268.             self.b1.fun_authors.order_by("first_name").all(),
    
  269.             [
    
  270.                 "Bugs",
    
  271.             ],
    
  272.             lambda c: c.first_name,
    
  273.             ordered=False,
    
  274.         )
    
  275.         self.assertQuerysetEqual(
    
  276.             self.b1.authors(manager="boring_people").all(),
    
  277.             [
    
  278.                 "Droopy",
    
  279.             ],
    
  280.             lambda c: c.first_name,
    
  281.             ordered=False,
    
  282.         )
    
  283.         self.assertQuerysetEqual(
    
  284.             self.b1.authors(manager="fun_people").all(),
    
  285.             [
    
  286.                 "Bugs",
    
  287.             ],
    
  288.             lambda c: c.first_name,
    
  289.             ordered=False,
    
  290.         )
    
  291. 
    
  292.     def test_removal_through_default_fk_related_manager(self, bulk=True):
    
  293.         bugs = FunPerson.objects.create(
    
  294.             first_name="Bugs", last_name="Bunny", fun=True, favorite_book=self.b1
    
  295.         )
    
  296.         droopy = FunPerson.objects.create(
    
  297.             first_name="Droopy", last_name="Dog", fun=False, favorite_book=self.b1
    
  298.         )
    
  299. 
    
  300.         self.b1.fun_people_favorite_books.remove(droopy, bulk=bulk)
    
  301.         self.assertQuerysetEqual(
    
  302.             FunPerson._base_manager.filter(favorite_book=self.b1),
    
  303.             [
    
  304.                 "Bugs",
    
  305.                 "Droopy",
    
  306.             ],
    
  307.             lambda c: c.first_name,
    
  308.             ordered=False,
    
  309.         )
    
  310. 
    
  311.         self.b1.fun_people_favorite_books.remove(bugs, bulk=bulk)
    
  312.         self.assertQuerysetEqual(
    
  313.             FunPerson._base_manager.filter(favorite_book=self.b1),
    
  314.             [
    
  315.                 "Droopy",
    
  316.             ],
    
  317.             lambda c: c.first_name,
    
  318.             ordered=False,
    
  319.         )
    
  320.         bugs.favorite_book = self.b1
    
  321.         bugs.save()
    
  322. 
    
  323.         self.b1.fun_people_favorite_books.clear(bulk=bulk)
    
  324.         self.assertQuerysetEqual(
    
  325.             FunPerson._base_manager.filter(favorite_book=self.b1),
    
  326.             [
    
  327.                 "Droopy",
    
  328.             ],
    
  329.             lambda c: c.first_name,
    
  330.             ordered=False,
    
  331.         )
    
  332. 
    
  333.     def test_slow_removal_through_default_fk_related_manager(self):
    
  334.         self.test_removal_through_default_fk_related_manager(bulk=False)
    
  335. 
    
  336.     def test_removal_through_specified_fk_related_manager(self, bulk=True):
    
  337.         Person.objects.create(
    
  338.             first_name="Bugs", last_name="Bunny", fun=True, favorite_book=self.b1
    
  339.         )
    
  340.         droopy = Person.objects.create(
    
  341.             first_name="Droopy", last_name="Dog", fun=False, favorite_book=self.b1
    
  342.         )
    
  343. 
    
  344.         # The fun manager DOESN'T remove boring people.
    
  345.         self.b1.favorite_books(manager="fun_people").remove(droopy, bulk=bulk)
    
  346.         self.assertQuerysetEqual(
    
  347.             self.b1.favorite_books(manager="boring_people").all(),
    
  348.             [
    
  349.                 "Droopy",
    
  350.             ],
    
  351.             lambda c: c.first_name,
    
  352.             ordered=False,
    
  353.         )
    
  354.         # The boring manager DOES remove boring people.
    
  355.         self.b1.favorite_books(manager="boring_people").remove(droopy, bulk=bulk)
    
  356.         self.assertQuerysetEqual(
    
  357.             self.b1.favorite_books(manager="boring_people").all(),
    
  358.             [],
    
  359.             lambda c: c.first_name,
    
  360.             ordered=False,
    
  361.         )
    
  362.         droopy.favorite_book = self.b1
    
  363.         droopy.save()
    
  364. 
    
  365.         # The fun manager ONLY clears fun people.
    
  366.         self.b1.favorite_books(manager="fun_people").clear(bulk=bulk)
    
  367.         self.assertQuerysetEqual(
    
  368.             self.b1.favorite_books(manager="boring_people").all(),
    
  369.             [
    
  370.                 "Droopy",
    
  371.             ],
    
  372.             lambda c: c.first_name,
    
  373.             ordered=False,
    
  374.         )
    
  375.         self.assertQuerysetEqual(
    
  376.             self.b1.favorite_books(manager="fun_people").all(),
    
  377.             [],
    
  378.             lambda c: c.first_name,
    
  379.             ordered=False,
    
  380.         )
    
  381. 
    
  382.     def test_slow_removal_through_specified_fk_related_manager(self):
    
  383.         self.test_removal_through_specified_fk_related_manager(bulk=False)
    
  384. 
    
  385.     def test_removal_through_default_gfk_related_manager(self, bulk=True):
    
  386.         bugs = FunPerson.objects.create(
    
  387.             first_name="Bugs", last_name="Bunny", fun=True, favorite_thing=self.b1
    
  388.         )
    
  389.         droopy = FunPerson.objects.create(
    
  390.             first_name="Droopy", last_name="Dog", fun=False, favorite_thing=self.b1
    
  391.         )
    
  392. 
    
  393.         self.b1.fun_people_favorite_things.remove(droopy, bulk=bulk)
    
  394.         self.assertQuerysetEqual(
    
  395.             FunPerson._base_manager.order_by("first_name").filter(
    
  396.                 favorite_thing_id=self.b1.pk
    
  397.             ),
    
  398.             [
    
  399.                 "Bugs",
    
  400.                 "Droopy",
    
  401.             ],
    
  402.             lambda c: c.first_name,
    
  403.             ordered=False,
    
  404.         )
    
  405. 
    
  406.         self.b1.fun_people_favorite_things.remove(bugs, bulk=bulk)
    
  407.         self.assertQuerysetEqual(
    
  408.             FunPerson._base_manager.order_by("first_name").filter(
    
  409.                 favorite_thing_id=self.b1.pk
    
  410.             ),
    
  411.             [
    
  412.                 "Droopy",
    
  413.             ],
    
  414.             lambda c: c.first_name,
    
  415.             ordered=False,
    
  416.         )
    
  417.         bugs.favorite_book = self.b1
    
  418.         bugs.save()
    
  419. 
    
  420.         self.b1.fun_people_favorite_things.clear(bulk=bulk)
    
  421.         self.assertQuerysetEqual(
    
  422.             FunPerson._base_manager.order_by("first_name").filter(
    
  423.                 favorite_thing_id=self.b1.pk
    
  424.             ),
    
  425.             [
    
  426.                 "Droopy",
    
  427.             ],
    
  428.             lambda c: c.first_name,
    
  429.             ordered=False,
    
  430.         )
    
  431. 
    
  432.     def test_slow_removal_through_default_gfk_related_manager(self):
    
  433.         self.test_removal_through_default_gfk_related_manager(bulk=False)
    
  434. 
    
  435.     def test_removal_through_specified_gfk_related_manager(self, bulk=True):
    
  436.         Person.objects.create(
    
  437.             first_name="Bugs", last_name="Bunny", fun=True, favorite_thing=self.b1
    
  438.         )
    
  439.         droopy = Person.objects.create(
    
  440.             first_name="Droopy", last_name="Dog", fun=False, favorite_thing=self.b1
    
  441.         )
    
  442. 
    
  443.         # The fun manager DOESN'T remove boring people.
    
  444.         self.b1.favorite_things(manager="fun_people").remove(droopy, bulk=bulk)
    
  445.         self.assertQuerysetEqual(
    
  446.             self.b1.favorite_things(manager="boring_people").all(),
    
  447.             [
    
  448.                 "Droopy",
    
  449.             ],
    
  450.             lambda c: c.first_name,
    
  451.             ordered=False,
    
  452.         )
    
  453. 
    
  454.         # The boring manager DOES remove boring people.
    
  455.         self.b1.favorite_things(manager="boring_people").remove(droopy, bulk=bulk)
    
  456.         self.assertQuerysetEqual(
    
  457.             self.b1.favorite_things(manager="boring_people").all(),
    
  458.             [],
    
  459.             lambda c: c.first_name,
    
  460.             ordered=False,
    
  461.         )
    
  462.         droopy.favorite_thing = self.b1
    
  463.         droopy.save()
    
  464. 
    
  465.         # The fun manager ONLY clears fun people.
    
  466.         self.b1.favorite_things(manager="fun_people").clear(bulk=bulk)
    
  467.         self.assertQuerysetEqual(
    
  468.             self.b1.favorite_things(manager="boring_people").all(),
    
  469.             [
    
  470.                 "Droopy",
    
  471.             ],
    
  472.             lambda c: c.first_name,
    
  473.             ordered=False,
    
  474.         )
    
  475.         self.assertQuerysetEqual(
    
  476.             self.b1.favorite_things(manager="fun_people").all(),
    
  477.             [],
    
  478.             lambda c: c.first_name,
    
  479.             ordered=False,
    
  480.         )
    
  481. 
    
  482.     def test_slow_removal_through_specified_gfk_related_manager(self):
    
  483.         self.test_removal_through_specified_gfk_related_manager(bulk=False)
    
  484. 
    
  485.     def test_removal_through_default_m2m_related_manager(self):
    
  486.         bugs = FunPerson.objects.create(first_name="Bugs", last_name="Bunny", fun=True)
    
  487.         self.b1.fun_authors.add(bugs)
    
  488.         droopy = FunPerson.objects.create(
    
  489.             first_name="Droopy", last_name="Dog", fun=False
    
  490.         )
    
  491.         self.b1.fun_authors.add(droopy)
    
  492. 
    
  493.         self.b1.fun_authors.remove(droopy)
    
  494.         self.assertQuerysetEqual(
    
  495.             self.b1.fun_authors.through._default_manager.all(),
    
  496.             [
    
  497.                 "Bugs",
    
  498.                 "Droopy",
    
  499.             ],
    
  500.             lambda c: c.funperson.first_name,
    
  501.             ordered=False,
    
  502.         )
    
  503. 
    
  504.         self.b1.fun_authors.remove(bugs)
    
  505.         self.assertQuerysetEqual(
    
  506.             self.b1.fun_authors.through._default_manager.all(),
    
  507.             [
    
  508.                 "Droopy",
    
  509.             ],
    
  510.             lambda c: c.funperson.first_name,
    
  511.             ordered=False,
    
  512.         )
    
  513.         self.b1.fun_authors.add(bugs)
    
  514. 
    
  515.         self.b1.fun_authors.clear()
    
  516.         self.assertQuerysetEqual(
    
  517.             self.b1.fun_authors.through._default_manager.all(),
    
  518.             [
    
  519.                 "Droopy",
    
  520.             ],
    
  521.             lambda c: c.funperson.first_name,
    
  522.             ordered=False,
    
  523.         )
    
  524. 
    
  525.     def test_removal_through_specified_m2m_related_manager(self):
    
  526.         bugs = Person.objects.create(first_name="Bugs", last_name="Bunny", fun=True)
    
  527.         self.b1.authors.add(bugs)
    
  528.         droopy = Person.objects.create(first_name="Droopy", last_name="Dog", fun=False)
    
  529.         self.b1.authors.add(droopy)
    
  530. 
    
  531.         # The fun manager DOESN'T remove boring people.
    
  532.         self.b1.authors(manager="fun_people").remove(droopy)
    
  533.         self.assertQuerysetEqual(
    
  534.             self.b1.authors(manager="boring_people").all(),
    
  535.             [
    
  536.                 "Droopy",
    
  537.             ],
    
  538.             lambda c: c.first_name,
    
  539.             ordered=False,
    
  540.         )
    
  541. 
    
  542.         # The boring manager DOES remove boring people.
    
  543.         self.b1.authors(manager="boring_people").remove(droopy)
    
  544.         self.assertQuerysetEqual(
    
  545.             self.b1.authors(manager="boring_people").all(),
    
  546.             [],
    
  547.             lambda c: c.first_name,
    
  548.             ordered=False,
    
  549.         )
    
  550.         self.b1.authors.add(droopy)
    
  551. 
    
  552.         # The fun manager ONLY clears fun people.
    
  553.         self.b1.authors(manager="fun_people").clear()
    
  554.         self.assertQuerysetEqual(
    
  555.             self.b1.authors(manager="boring_people").all(),
    
  556.             [
    
  557.                 "Droopy",
    
  558.             ],
    
  559.             lambda c: c.first_name,
    
  560.             ordered=False,
    
  561.         )
    
  562.         self.assertQuerysetEqual(
    
  563.             self.b1.authors(manager="fun_people").all(),
    
  564.             [],
    
  565.             lambda c: c.first_name,
    
  566.             ordered=False,
    
  567.         )
    
  568. 
    
  569.     def test_deconstruct_default(self):
    
  570.         mgr = models.Manager()
    
  571.         as_manager, mgr_path, qs_path, args, kwargs = mgr.deconstruct()
    
  572.         self.assertFalse(as_manager)
    
  573.         self.assertEqual(mgr_path, "django.db.models.manager.Manager")
    
  574.         self.assertEqual(args, ())
    
  575.         self.assertEqual(kwargs, {})
    
  576. 
    
  577.     def test_deconstruct_as_manager(self):
    
  578.         mgr = CustomQuerySet.as_manager()
    
  579.         as_manager, mgr_path, qs_path, args, kwargs = mgr.deconstruct()
    
  580.         self.assertTrue(as_manager)
    
  581.         self.assertEqual(qs_path, "custom_managers.models.CustomQuerySet")
    
  582. 
    
  583.     def test_deconstruct_from_queryset(self):
    
  584.         mgr = DeconstructibleCustomManager("a", "b")
    
  585.         as_manager, mgr_path, qs_path, args, kwargs = mgr.deconstruct()
    
  586.         self.assertFalse(as_manager)
    
  587.         self.assertEqual(
    
  588.             mgr_path, "custom_managers.models.DeconstructibleCustomManager"
    
  589.         )
    
  590.         self.assertEqual(
    
  591.             args,
    
  592.             (
    
  593.                 "a",
    
  594.                 "b",
    
  595.             ),
    
  596.         )
    
  597.         self.assertEqual(kwargs, {})
    
  598. 
    
  599.         mgr = DeconstructibleCustomManager("x", "y", c=3, d=4)
    
  600.         as_manager, mgr_path, qs_path, args, kwargs = mgr.deconstruct()
    
  601.         self.assertFalse(as_manager)
    
  602.         self.assertEqual(
    
  603.             mgr_path, "custom_managers.models.DeconstructibleCustomManager"
    
  604.         )
    
  605.         self.assertEqual(
    
  606.             args,
    
  607.             (
    
  608.                 "x",
    
  609.                 "y",
    
  610.             ),
    
  611.         )
    
  612.         self.assertEqual(kwargs, {"c": 3, "d": 4})
    
  613. 
    
  614.     def test_deconstruct_from_queryset_failing(self):
    
  615.         mgr = CustomManager("arg")
    
  616.         msg = (
    
  617.             "Could not find manager BaseCustomManagerFromCustomQuerySet in "
    
  618.             "django.db.models.manager.\n"
    
  619.             "Please note that you need to inherit from managers you "
    
  620.             "dynamically generated with 'from_queryset()'."
    
  621.         )
    
  622.         with self.assertRaisesMessage(ValueError, msg):
    
  623.             mgr.deconstruct()
    
  624. 
    
  625.     def test_abstract_model_with_custom_manager_name(self):
    
  626.         """
    
  627.         A custom manager may be defined on an abstract model.
    
  628.         It will be inherited by the abstract model's children.
    
  629.         """
    
  630.         PersonFromAbstract.abstract_persons.create(objects="Test")
    
  631.         self.assertQuerysetEqual(
    
  632.             PersonFromAbstract.abstract_persons.all(),
    
  633.             ["Test"],
    
  634.             lambda c: c.objects,
    
  635.         )
    
  636. 
    
  637. 
    
  638. class TestCars(TestCase):
    
  639.     def test_managers(self):
    
  640.         # Each model class gets a "_default_manager" attribute, which is a
    
  641.         # reference to the first manager defined in the class.
    
  642.         Car.cars.create(name="Corvette", mileage=21, top_speed=180)
    
  643.         Car.cars.create(name="Neon", mileage=31, top_speed=100)
    
  644. 
    
  645.         self.assertQuerysetEqual(
    
  646.             Car._default_manager.order_by("name"),
    
  647.             [
    
  648.                 "Corvette",
    
  649.                 "Neon",
    
  650.             ],
    
  651.             lambda c: c.name,
    
  652.         )
    
  653.         self.assertQuerysetEqual(
    
  654.             Car.cars.order_by("name"),
    
  655.             [
    
  656.                 "Corvette",
    
  657.                 "Neon",
    
  658.             ],
    
  659.             lambda c: c.name,
    
  660.         )
    
  661.         # alternate manager
    
  662.         self.assertQuerysetEqual(
    
  663.             Car.fast_cars.all(),
    
  664.             [
    
  665.                 "Corvette",
    
  666.             ],
    
  667.             lambda c: c.name,
    
  668.         )
    
  669.         # explicit default manager
    
  670.         self.assertQuerysetEqual(
    
  671.             FastCarAsDefault.cars.order_by("name"),
    
  672.             [
    
  673.                 "Corvette",
    
  674.                 "Neon",
    
  675.             ],
    
  676.             lambda c: c.name,
    
  677.         )
    
  678.         self.assertQuerysetEqual(
    
  679.             FastCarAsDefault._default_manager.all(),
    
  680.             [
    
  681.                 "Corvette",
    
  682.             ],
    
  683.             lambda c: c.name,
    
  684.         )
    
  685.         # explicit base manager
    
  686.         self.assertQuerysetEqual(
    
  687.             FastCarAsBase.cars.order_by("name"),
    
  688.             [
    
  689.                 "Corvette",
    
  690.                 "Neon",
    
  691.             ],
    
  692.             lambda c: c.name,
    
  693.         )
    
  694.         self.assertQuerysetEqual(
    
  695.             FastCarAsBase._base_manager.all(),
    
  696.             [
    
  697.                 "Corvette",
    
  698.             ],
    
  699.             lambda c: c.name,
    
  700.         )
    
  701. 
    
  702. 
    
  703. class CustomManagersRegressTestCase(TestCase):
    
  704.     def test_filtered_default_manager(self):
    
  705.         """Even though the default manager filters out some records,
    
  706.         we must still be able to save (particularly, save by updating
    
  707.         existing records) those filtered instances. This is a
    
  708.         regression test for #8990, #9527"""
    
  709.         related = RelatedModel.objects.create(name="xyzzy")
    
  710.         obj = RestrictedModel.objects.create(name="hidden", related=related)
    
  711.         obj.name = "still hidden"
    
  712.         obj.save()
    
  713. 
    
  714.         # If the hidden object wasn't seen during the save process,
    
  715.         # there would now be two objects in the database.
    
  716.         self.assertEqual(RestrictedModel.plain_manager.count(), 1)
    
  717. 
    
  718.     def test_refresh_from_db_when_default_manager_filters(self):
    
  719.         """
    
  720.         Model.refresh_from_db() works for instances hidden by the default
    
  721.         manager.
    
  722.         """
    
  723.         book = Book._base_manager.create(is_published=False)
    
  724.         Book._base_manager.filter(pk=book.pk).update(title="Hi")
    
  725.         book.refresh_from_db()
    
  726.         self.assertEqual(book.title, "Hi")
    
  727. 
    
  728.     def test_save_clears_annotations_from_base_manager(self):
    
  729.         """Model.save() clears annotations from the base manager."""
    
  730.         self.assertEqual(Book._meta.base_manager.name, "annotated_objects")
    
  731.         book = Book.annotated_objects.create(title="Hunting")
    
  732.         Person.objects.create(
    
  733.             first_name="Bugs",
    
  734.             last_name="Bunny",
    
  735.             fun=True,
    
  736.             favorite_book=book,
    
  737.             favorite_thing_id=1,
    
  738.         )
    
  739.         book = Book.annotated_objects.first()
    
  740.         self.assertEqual(book.favorite_avg, 1)  # Annotation from the manager.
    
  741.         book.title = "New Hunting"
    
  742.         # save() fails if annotations that involve related fields aren't
    
  743.         # cleared before the update query.
    
  744.         book.save()
    
  745.         self.assertEqual(Book.annotated_objects.first().title, "New Hunting")
    
  746. 
    
  747.     def test_delete_related_on_filtered_manager(self):
    
  748.         """Deleting related objects should also not be distracted by a
    
  749.         restricted manager on the related object. This is a regression
    
  750.         test for #2698."""
    
  751.         related = RelatedModel.objects.create(name="xyzzy")
    
  752. 
    
  753.         for name, public in (("one", True), ("two", False), ("three", False)):
    
  754.             RestrictedModel.objects.create(name=name, is_public=public, related=related)
    
  755. 
    
  756.         obj = RelatedModel.objects.get(name="xyzzy")
    
  757.         obj.delete()
    
  758. 
    
  759.         # All of the RestrictedModel instances should have been
    
  760.         # deleted, since they *all* pointed to the RelatedModel. If
    
  761.         # the default manager is used, only the public one will be
    
  762.         # deleted.
    
  763.         self.assertEqual(len(RestrictedModel.plain_manager.all()), 0)
    
  764. 
    
  765.     def test_delete_one_to_one_manager(self):
    
  766.         # The same test case as the last one, but for one-to-one
    
  767.         # models, which are implemented slightly different internally,
    
  768.         # so it's a different code path.
    
  769.         obj = RelatedModel.objects.create(name="xyzzy")
    
  770.         OneToOneRestrictedModel.objects.create(name="foo", is_public=False, related=obj)
    
  771.         obj = RelatedModel.objects.get(name="xyzzy")
    
  772.         obj.delete()
    
  773.         self.assertEqual(len(OneToOneRestrictedModel.plain_manager.all()), 0)
    
  774. 
    
  775.     def test_queryset_with_custom_init(self):
    
  776.         """
    
  777.         BaseManager.get_queryset() should use kwargs rather than args to allow
    
  778.         custom kwargs (#24911).
    
  779.         """
    
  780.         qs_custom = Person.custom_init_queryset_manager.all()
    
  781.         qs_default = Person.objects.all()
    
  782.         self.assertQuerysetEqual(qs_custom, qs_default)