tests.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. from __future__ import unicode_literals
  2. from django.db import models
  3. from django.template import Context, Template
  4. from django.test import TestCase, override_settings
  5. from django.test.utils import isolate_apps
  6. from django.utils.encoding import force_text
  7. from .models import (
  8. AbstractBase1, AbstractBase2, AbstractBase3, Child1, Child2, Child3,
  9. Child4, Child5, Child6, Child7, RelatedModel, RelationModel,
  10. )
  11. class ManagersRegressionTests(TestCase):
  12. def test_managers(self):
  13. Child1.objects.create(name='fred', data='a1')
  14. Child1.objects.create(name='barney', data='a2')
  15. Child2.objects.create(name='fred', data='b1', value=1)
  16. Child2.objects.create(name='barney', data='b2', value=42)
  17. Child3.objects.create(name='fred', data='c1', comment='yes')
  18. Child3.objects.create(name='barney', data='c2', comment='no')
  19. Child4.objects.create(name='fred', data='d1')
  20. Child4.objects.create(name='barney', data='d2')
  21. Child5.objects.create(name='fred', comment='yes')
  22. Child5.objects.create(name='barney', comment='no')
  23. Child6.objects.create(name='fred', data='f1', value=42)
  24. Child6.objects.create(name='barney', data='f2', value=42)
  25. Child7.objects.create(name='fred')
  26. Child7.objects.create(name='barney')
  27. self.assertQuerysetEqual(Child1.manager1.all(), ["<Child1: a1>"])
  28. self.assertQuerysetEqual(Child1.manager2.all(), ["<Child1: a2>"])
  29. self.assertQuerysetEqual(Child1._default_manager.all(), ["<Child1: a1>"])
  30. self.assertQuerysetEqual(Child2._default_manager.all(), ["<Child2: b1>"])
  31. self.assertQuerysetEqual(Child2.restricted.all(), ["<Child2: b2>"])
  32. self.assertQuerysetEqual(Child3._default_manager.all(), ["<Child3: c1>"])
  33. self.assertQuerysetEqual(Child3.manager1.all(), ["<Child3: c1>"])
  34. self.assertQuerysetEqual(Child3.manager2.all(), ["<Child3: c2>"])
  35. # Since Child6 inherits from Child4, the corresponding rows from f1 and
  36. # f2 also appear here. This is the expected result.
  37. self.assertQuerysetEqual(Child4._default_manager.order_by('data'), [
  38. "<Child4: d1>",
  39. "<Child4: d2>",
  40. "<Child4: f1>",
  41. "<Child4: f2>",
  42. ])
  43. self.assertQuerysetEqual(Child4.manager1.all(), ["<Child4: d1>", "<Child4: f1>"], ordered=False)
  44. self.assertQuerysetEqual(Child5._default_manager.all(), ["<Child5: fred>"])
  45. self.assertQuerysetEqual(Child6._default_manager.all(), ["<Child6: f1>", "<Child6: f2>"], ordered=False)
  46. self.assertQuerysetEqual(
  47. Child7._default_manager.order_by('name'),
  48. ["<Child7: barney>", "<Child7: fred>"]
  49. )
  50. def test_abstract_manager(self):
  51. # Accessing the manager on an abstract model should
  52. # raise an attribute error with an appropriate message.
  53. # This error message isn't ideal, but if the model is abstract and
  54. # a lot of the class instantiation logic isn't invoked; if the
  55. # manager is implied, then we don't get a hook to install the
  56. # error-raising manager.
  57. msg = "type object 'AbstractBase3' has no attribute 'objects'"
  58. with self.assertRaisesMessage(AttributeError, msg):
  59. AbstractBase3.objects.all()
  60. def test_custom_abstract_manager(self):
  61. # Accessing the manager on an abstract model with an custom
  62. # manager should raise an attribute error with an appropriate
  63. # message.
  64. msg = "Manager isn't available; AbstractBase2 is abstract"
  65. with self.assertRaisesMessage(AttributeError, msg):
  66. AbstractBase2.restricted.all()
  67. def test_explicit_abstract_manager(self):
  68. # Accessing the manager on an abstract model with an explicit
  69. # manager should raise an attribute error with an appropriate
  70. # message.
  71. msg = "Manager isn't available; AbstractBase1 is abstract"
  72. with self.assertRaisesMessage(AttributeError, msg):
  73. AbstractBase1.objects.all()
  74. @override_settings(TEST_SWAPPABLE_MODEL='managers_regress.Parent')
  75. @isolate_apps('managers_regress')
  76. def test_swappable_manager(self):
  77. class SwappableModel(models.Model):
  78. class Meta:
  79. swappable = 'TEST_SWAPPABLE_MODEL'
  80. # Accessing the manager on a swappable model should
  81. # raise an attribute error with a helpful message
  82. msg = (
  83. "Manager isn't available; 'managers_regress.SwappableModel' "
  84. "has been swapped for 'managers_regress.Parent'"
  85. )
  86. with self.assertRaisesMessage(AttributeError, msg):
  87. SwappableModel.objects.all()
  88. @override_settings(TEST_SWAPPABLE_MODEL='managers_regress.Parent')
  89. @isolate_apps('managers_regress')
  90. def test_custom_swappable_manager(self):
  91. class SwappableModel(models.Model):
  92. stuff = models.Manager()
  93. class Meta:
  94. swappable = 'TEST_SWAPPABLE_MODEL'
  95. # Accessing the manager on a swappable model with an
  96. # explicit manager should raise an attribute error with a
  97. # helpful message
  98. msg = (
  99. "Manager isn't available; 'managers_regress.SwappableModel' "
  100. "has been swapped for 'managers_regress.Parent'"
  101. )
  102. with self.assertRaisesMessage(AttributeError, msg):
  103. SwappableModel.stuff.all()
  104. @override_settings(TEST_SWAPPABLE_MODEL='managers_regress.Parent')
  105. @isolate_apps('managers_regress')
  106. def test_explicit_swappable_manager(self):
  107. class SwappableModel(models.Model):
  108. objects = models.Manager()
  109. class Meta:
  110. swappable = 'TEST_SWAPPABLE_MODEL'
  111. # Accessing the manager on a swappable model with an
  112. # explicit manager should raise an attribute error with a
  113. # helpful message
  114. msg = (
  115. "Manager isn't available; 'managers_regress.SwappableModel' "
  116. "has been swapped for 'managers_regress.Parent'"
  117. )
  118. with self.assertRaisesMessage(AttributeError, msg):
  119. SwappableModel.objects.all()
  120. def test_regress_3871(self):
  121. related = RelatedModel.objects.create()
  122. relation = RelationModel()
  123. relation.fk = related
  124. relation.gfk = related
  125. relation.save()
  126. relation.m2m.add(related)
  127. t = Template('{{ related.test_fk.all.0 }}{{ related.test_gfk.all.0 }}{{ related.test_m2m.all.0 }}')
  128. self.assertEqual(
  129. t.render(Context({'related': related})),
  130. ''.join([force_text(relation.pk)] * 3),
  131. )
  132. def test_field_can_be_called_exact(self):
  133. # Make sure related managers core filters don't include an
  134. # explicit `__exact` lookup that could be interpreted as a
  135. # reference to a foreign `exact` field. refs #23940.
  136. related = RelatedModel.objects.create(exact=False)
  137. relation = related.test_fk.create()
  138. self.assertEqual(related.test_fk.get(), relation)