tests.py 26 KB

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