tests.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. from django.db import models
  2. from django.template import Context, Template
  3. from django.test import TestCase, override_settings
  4. from django.test.utils import isolate_apps
  5. from .models import (
  6. AbstractBase1, AbstractBase2, AbstractBase3, Child1, Child2, Child3,
  7. Child4, Child5, Child6, Child7, RelatedModel, RelationModel,
  8. )
  9. class ManagersRegressionTests(TestCase):
  10. def test_managers(self):
  11. Child1.objects.create(name='fred', data='a1')
  12. Child1.objects.create(name='barney', data='a2')
  13. Child2.objects.create(name='fred', data='b1', value=1)
  14. Child2.objects.create(name='barney', data='b2', value=42)
  15. Child3.objects.create(name='fred', data='c1', comment='yes')
  16. Child3.objects.create(name='barney', data='c2', comment='no')
  17. Child4.objects.create(name='fred', data='d1')
  18. Child4.objects.create(name='barney', data='d2')
  19. Child5.objects.create(name='fred', comment='yes')
  20. Child5.objects.create(name='barney', comment='no')
  21. Child6.objects.create(name='fred', data='f1', value=42)
  22. Child6.objects.create(name='barney', data='f2', value=42)
  23. Child7.objects.create(name='fred')
  24. Child7.objects.create(name='barney')
  25. self.assertQuerysetEqual(Child1.manager1.all(), ["<Child1: a1>"])
  26. self.assertQuerysetEqual(Child1.manager2.all(), ["<Child1: a2>"])
  27. self.assertQuerysetEqual(Child1._default_manager.all(), ["<Child1: a1>"])
  28. self.assertQuerysetEqual(Child2._default_manager.all(), ["<Child2: b1>"])
  29. self.assertQuerysetEqual(Child2.restricted.all(), ["<Child2: b2>"])
  30. self.assertQuerysetEqual(Child3._default_manager.all(), ["<Child3: c1>"])
  31. self.assertQuerysetEqual(Child3.manager1.all(), ["<Child3: c1>"])
  32. self.assertQuerysetEqual(Child3.manager2.all(), ["<Child3: c2>"])
  33. # Since Child6 inherits from Child4, the corresponding rows from f1 and
  34. # f2 also appear here. This is the expected result.
  35. self.assertQuerysetEqual(Child4._default_manager.order_by('data'), [
  36. "<Child4: d1>",
  37. "<Child4: d2>",
  38. "<Child4: f1>",
  39. "<Child4: f2>",
  40. ])
  41. self.assertQuerysetEqual(Child4.manager1.all(), ["<Child4: d1>", "<Child4: f1>"], ordered=False)
  42. self.assertQuerysetEqual(Child5._default_manager.all(), ["<Child5: fred>"])
  43. self.assertQuerysetEqual(Child6._default_manager.all(), ["<Child6: f1>", "<Child6: f2>"], ordered=False)
  44. self.assertQuerysetEqual(
  45. Child7._default_manager.order_by('name'),
  46. ["<Child7: barney>", "<Child7: fred>"]
  47. )
  48. def test_abstract_manager(self):
  49. # Accessing the manager on an abstract model should
  50. # raise an attribute error with an appropriate message.
  51. # This error message isn't ideal, but if the model is abstract and
  52. # a lot of the class instantiation logic isn't invoked; if the
  53. # manager is implied, then we don't get a hook to install the
  54. # error-raising manager.
  55. msg = "type object 'AbstractBase3' has no attribute 'objects'"
  56. with self.assertRaisesMessage(AttributeError, msg):
  57. AbstractBase3.objects.all()
  58. def test_custom_abstract_manager(self):
  59. # Accessing the manager on an abstract model with a custom
  60. # manager should raise an attribute error with an appropriate
  61. # message.
  62. msg = "Manager isn't available; AbstractBase2 is abstract"
  63. with self.assertRaisesMessage(AttributeError, msg):
  64. AbstractBase2.restricted.all()
  65. def test_explicit_abstract_manager(self):
  66. # Accessing the manager on an abstract model with an explicit
  67. # manager should raise an attribute error with an appropriate
  68. # message.
  69. msg = "Manager isn't available; AbstractBase1 is abstract"
  70. with self.assertRaisesMessage(AttributeError, msg):
  71. AbstractBase1.objects.all()
  72. @override_settings(TEST_SWAPPABLE_MODEL='managers_regress.Parent')
  73. @isolate_apps('managers_regress')
  74. def test_swappable_manager(self):
  75. class SwappableModel(models.Model):
  76. class Meta:
  77. swappable = 'TEST_SWAPPABLE_MODEL'
  78. # Accessing the manager on a swappable model should
  79. # raise an attribute error with a helpful message
  80. msg = (
  81. "Manager isn't available; 'managers_regress.SwappableModel' "
  82. "has been swapped for 'managers_regress.Parent'"
  83. )
  84. with self.assertRaisesMessage(AttributeError, msg):
  85. SwappableModel.objects.all()
  86. @override_settings(TEST_SWAPPABLE_MODEL='managers_regress.Parent')
  87. @isolate_apps('managers_regress')
  88. def test_custom_swappable_manager(self):
  89. class SwappableModel(models.Model):
  90. stuff = models.Manager()
  91. class Meta:
  92. swappable = 'TEST_SWAPPABLE_MODEL'
  93. # Accessing the manager on a swappable model with an
  94. # explicit manager should raise an attribute error with a
  95. # helpful message
  96. msg = (
  97. "Manager isn't available; 'managers_regress.SwappableModel' "
  98. "has been swapped for 'managers_regress.Parent'"
  99. )
  100. with self.assertRaisesMessage(AttributeError, msg):
  101. SwappableModel.stuff.all()
  102. @override_settings(TEST_SWAPPABLE_MODEL='managers_regress.Parent')
  103. @isolate_apps('managers_regress')
  104. def test_explicit_swappable_manager(self):
  105. class SwappableModel(models.Model):
  106. objects = models.Manager()
  107. class Meta:
  108. swappable = 'TEST_SWAPPABLE_MODEL'
  109. # Accessing the manager on a swappable model with an
  110. # explicit manager should raise an attribute error with a
  111. # helpful message
  112. msg = (
  113. "Manager isn't available; 'managers_regress.SwappableModel' "
  114. "has been swapped for 'managers_regress.Parent'"
  115. )
  116. with self.assertRaisesMessage(AttributeError, msg):
  117. SwappableModel.objects.all()
  118. def test_regress_3871(self):
  119. related = RelatedModel.objects.create()
  120. relation = RelationModel()
  121. relation.fk = related
  122. relation.gfk = related
  123. relation.save()
  124. relation.m2m.add(related)
  125. t = Template('{{ related.test_fk.all.0 }}{{ related.test_gfk.all.0 }}{{ related.test_m2m.all.0 }}')
  126. self.assertEqual(
  127. t.render(Context({'related': related})),
  128. ''.join([str(relation.pk)] * 3),
  129. )
  130. def test_field_can_be_called_exact(self):
  131. # Make sure related managers core filters don't include an
  132. # explicit `__exact` lookup that could be interpreted as a
  133. # reference to a foreign `exact` field. refs #23940.
  134. related = RelatedModel.objects.create(exact=False)
  135. relation = related.test_fk.create()
  136. self.assertEqual(related.test_fk.get(), relation)
  137. @isolate_apps('managers_regress')
  138. class TestManagerInheritance(TestCase):
  139. def test_implicit_inheritance(self):
  140. class CustomManager(models.Manager):
  141. pass
  142. class AbstractModel(models.Model):
  143. custom_manager = CustomManager()
  144. class Meta:
  145. abstract = True
  146. class PlainModel(models.Model):
  147. custom_manager = CustomManager()
  148. self.assertIsInstance(PlainModel._base_manager, models.Manager)
  149. self.assertIsInstance(PlainModel._default_manager, CustomManager)
  150. class ModelWithAbstractParent(AbstractModel):
  151. pass
  152. self.assertIsInstance(ModelWithAbstractParent._base_manager, models.Manager)
  153. self.assertIsInstance(ModelWithAbstractParent._default_manager, CustomManager)
  154. class ProxyModel(PlainModel):
  155. class Meta:
  156. proxy = True
  157. self.assertIsInstance(ProxyModel._base_manager, models.Manager)
  158. self.assertIsInstance(ProxyModel._default_manager, CustomManager)
  159. class MTIModel(PlainModel):
  160. pass
  161. self.assertIsInstance(MTIModel._base_manager, models.Manager)
  162. self.assertIsInstance(MTIModel._default_manager, CustomManager)
  163. def test_default_manager_inheritance(self):
  164. class CustomManager(models.Manager):
  165. pass
  166. class AbstractModel(models.Model):
  167. another_manager = models.Manager()
  168. custom_manager = CustomManager()
  169. class Meta:
  170. default_manager_name = 'custom_manager'
  171. abstract = True
  172. class PlainModel(models.Model):
  173. another_manager = models.Manager()
  174. custom_manager = CustomManager()
  175. class Meta:
  176. default_manager_name = 'custom_manager'
  177. self.assertIsInstance(PlainModel._default_manager, CustomManager)
  178. class ModelWithAbstractParent(AbstractModel):
  179. pass
  180. self.assertIsInstance(ModelWithAbstractParent._default_manager, CustomManager)
  181. class ProxyModel(PlainModel):
  182. class Meta:
  183. proxy = True
  184. self.assertIsInstance(ProxyModel._default_manager, CustomManager)
  185. class MTIModel(PlainModel):
  186. pass
  187. self.assertIsInstance(MTIModel._default_manager, CustomManager)
  188. def test_base_manager_inheritance(self):
  189. class CustomManager(models.Manager):
  190. pass
  191. class AbstractModel(models.Model):
  192. another_manager = models.Manager()
  193. custom_manager = CustomManager()
  194. class Meta:
  195. base_manager_name = 'custom_manager'
  196. abstract = True
  197. class PlainModel(models.Model):
  198. another_manager = models.Manager()
  199. custom_manager = CustomManager()
  200. class Meta:
  201. base_manager_name = 'custom_manager'
  202. self.assertIsInstance(PlainModel._base_manager, CustomManager)
  203. class ModelWithAbstractParent(AbstractModel):
  204. pass
  205. self.assertIsInstance(ModelWithAbstractParent._base_manager, CustomManager)
  206. class ProxyModel(PlainModel):
  207. class Meta:
  208. proxy = True
  209. self.assertIsInstance(ProxyModel._base_manager, CustomManager)
  210. class MTIModel(PlainModel):
  211. pass
  212. self.assertIsInstance(MTIModel._base_manager, CustomManager)
  213. def test_manager_no_duplicates(self):
  214. class CustomManager(models.Manager):
  215. pass
  216. class AbstractModel(models.Model):
  217. custom_manager = models.Manager()
  218. class Meta:
  219. abstract = True
  220. class TestModel(AbstractModel):
  221. custom_manager = CustomManager()
  222. self.assertEqual(TestModel._meta.managers, (TestModel.custom_manager,))
  223. self.assertEqual(TestModel._meta.managers_map, {'custom_manager': TestModel.custom_manager})