tests.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. import datetime
  2. from operator import attrgetter
  3. from .models import Country, Person, Group, Membership, Friendship, Article, ArticleTranslation
  4. from django.test import TestCase
  5. from django.utils.translation import activate
  6. from django import forms
  7. class MultiColumnFKTests(TestCase):
  8. def setUp(self):
  9. # Creating countries
  10. self.usa = Country.objects.create(name="United States of America")
  11. self.soviet_union = Country.objects.create(name="Soviet Union")
  12. Person()
  13. # Creating People
  14. self.bob = Person()
  15. self.bob.name = 'Bob'
  16. self.bob.person_country = self.usa
  17. self.bob.save()
  18. self.jim = Person.objects.create(name='Jim', person_country=self.usa)
  19. self.george = Person.objects.create(name='George', person_country=self.usa)
  20. self.jane = Person.objects.create(name='Jane', person_country=self.soviet_union)
  21. self.mark = Person.objects.create(name='Mark', person_country=self.soviet_union)
  22. self.sam = Person.objects.create(name='Sam', person_country=self.soviet_union)
  23. # Creating Groups
  24. self.kgb = Group.objects.create(name='KGB', group_country=self.soviet_union)
  25. self.cia = Group.objects.create(name='CIA', group_country=self.usa)
  26. self.republican = Group.objects.create(name='Republican', group_country=self.usa)
  27. self.democrat = Group.objects.create(name='Democrat', group_country=self.usa)
  28. def test_get_succeeds_on_multicolumn_match(self):
  29. # Membership objects have access to their related Person if both
  30. # country_ids match between them
  31. membership = Membership.objects.create(
  32. membership_country_id=self.usa.id, person_id=self.bob.id, group_id=self.cia.id)
  33. person = membership.person
  34. self.assertEqual((person.id, person.name), (self.bob.id, "Bob"))
  35. def test_get_fails_on_multicolumn_mismatch(self):
  36. # Membership objects returns DoesNotExist error when the there is no
  37. # Person with the same id and country_id
  38. membership = Membership.objects.create(
  39. membership_country_id=self.usa.id, person_id=self.jane.id, group_id=self.cia.id)
  40. self.assertRaises(Person.DoesNotExist, getattr, membership, 'person')
  41. def test_reverse_query_returns_correct_result(self):
  42. # Creating a valid membership because it has the same country has the person
  43. Membership.objects.create(
  44. membership_country_id=self.usa.id, person_id=self.bob.id, group_id=self.cia.id)
  45. # Creating an invalid membership because it has a different country has the person
  46. Membership.objects.create(
  47. membership_country_id=self.soviet_union.id, person_id=self.bob.id,
  48. group_id=self.republican.id)
  49. self.assertQuerysetEqual(
  50. self.bob.membership_set.all(), [
  51. self.cia.id
  52. ],
  53. attrgetter("group_id")
  54. )
  55. def test_query_filters_correctly(self):
  56. # Creating a to valid memberships
  57. Membership.objects.create(
  58. membership_country_id=self.usa.id, person_id=self.bob.id, group_id=self.cia.id)
  59. Membership.objects.create(
  60. membership_country_id=self.usa.id, person_id=self.jim.id,
  61. group_id=self.cia.id)
  62. # Creating an invalid membership
  63. Membership.objects.create(membership_country_id=self.soviet_union.id,
  64. person_id=self.george.id, group_id=self.cia.id)
  65. self.assertQuerysetEqual(
  66. Membership.objects.filter(person__name__contains='o'), [
  67. self.bob.id
  68. ],
  69. attrgetter("person_id")
  70. )
  71. def test_reverse_query_filters_correctly(self):
  72. timemark = datetime.datetime.utcnow()
  73. timedelta = datetime.timedelta(days=1)
  74. # Creating a to valid memberships
  75. Membership.objects.create(
  76. membership_country_id=self.usa.id, person_id=self.bob.id,
  77. group_id=self.cia.id, date_joined=timemark - timedelta)
  78. Membership.objects.create(
  79. membership_country_id=self.usa.id, person_id=self.jim.id,
  80. group_id=self.cia.id, date_joined=timemark + timedelta)
  81. # Creating an invalid membership
  82. Membership.objects.create(
  83. membership_country_id=self.soviet_union.id, person_id=self.george.id,
  84. group_id=self.cia.id, date_joined=timemark + timedelta)
  85. self.assertQuerysetEqual(
  86. Person.objects.filter(membership__date_joined__gte=timemark), [
  87. 'Jim'
  88. ],
  89. attrgetter('name')
  90. )
  91. def test_forward_in_lookup_filters_correctly(self):
  92. Membership.objects.create(membership_country_id=self.usa.id, person_id=self.bob.id,
  93. group_id=self.cia.id)
  94. Membership.objects.create(membership_country_id=self.usa.id, person_id=self.jim.id,
  95. group_id=self.cia.id)
  96. # Creating an invalid membership
  97. Membership.objects.create(
  98. membership_country_id=self.soviet_union.id, person_id=self.george.id,
  99. group_id=self.cia.id)
  100. self.assertQuerysetEqual(
  101. Membership.objects.filter(person__in=[self.george, self.jim]), [
  102. self.jim.id,
  103. ],
  104. attrgetter('person_id')
  105. )
  106. self.assertQuerysetEqual(
  107. Membership.objects.filter(person__in=Person.objects.filter(name='Jim')), [
  108. self.jim.id,
  109. ],
  110. attrgetter('person_id')
  111. )
  112. def test_select_related_foreignkey_forward_works(self):
  113. Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
  114. Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.democrat)
  115. with self.assertNumQueries(1):
  116. people = [m.person for m in Membership.objects.select_related('person')]
  117. normal_people = [m.person for m in Membership.objects.all()]
  118. self.assertEqual(people, normal_people)
  119. def test_prefetch_foreignkey_forward_works(self):
  120. Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
  121. Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.democrat)
  122. with self.assertNumQueries(2):
  123. people = [m.person for m in Membership.objects.prefetch_related('person')]
  124. normal_people = [m.person for m in Membership.objects.all()]
  125. self.assertEqual(people, normal_people)
  126. def test_prefetch_foreignkey_reverse_works(self):
  127. Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
  128. Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.democrat)
  129. with self.assertNumQueries(2):
  130. membership_sets = [list(p.membership_set.all())
  131. for p in Person.objects.prefetch_related('membership_set')]
  132. normal_membership_sets = [list(p.membership_set.all()) for p in Person.objects.all()]
  133. self.assertEqual(membership_sets, normal_membership_sets)
  134. def test_m2m_through_forward_returns_valid_members(self):
  135. # We start out by making sure that the Group 'CIA' has no members.
  136. self.assertQuerysetEqual(
  137. self.cia.members.all(),
  138. []
  139. )
  140. Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
  141. Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.cia)
  142. # Let's check to make sure that it worked. Bob and Jim should be members of the CIA.
  143. self.assertQuerysetEqual(
  144. self.cia.members.all(), [
  145. 'Bob',
  146. 'Jim'
  147. ], attrgetter("name")
  148. )
  149. def test_m2m_through_reverse_returns_valid_members(self):
  150. # We start out by making sure that Bob is in no groups.
  151. self.assertQuerysetEqual(
  152. self.bob.groups.all(),
  153. []
  154. )
  155. Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
  156. Membership.objects.create(membership_country=self.usa, person=self.bob,
  157. group=self.republican)
  158. # Bob should be in the CIA and a Republican
  159. self.assertQuerysetEqual(
  160. self.bob.groups.all(), [
  161. 'CIA',
  162. 'Republican'
  163. ], attrgetter("name")
  164. )
  165. def test_m2m_through_forward_ignores_invalid_members(self):
  166. # We start out by making sure that the Group 'CIA' has no members.
  167. self.assertQuerysetEqual(
  168. self.cia.members.all(),
  169. []
  170. )
  171. # Something adds jane to group CIA but Jane is in Soviet Union which isn't CIA's country
  172. Membership.objects.create(membership_country=self.usa, person=self.jane, group=self.cia)
  173. # There should still be no members in CIA
  174. self.assertQuerysetEqual(
  175. self.cia.members.all(),
  176. []
  177. )
  178. def test_m2m_through_reverse_ignores_invalid_members(self):
  179. # We start out by making sure that Jane has no groups.
  180. self.assertQuerysetEqual(
  181. self.jane.groups.all(),
  182. []
  183. )
  184. # Something adds jane to group CIA but Jane is in Soviet Union which isn't CIA's country
  185. Membership.objects.create(membership_country=self.usa, person=self.jane, group=self.cia)
  186. # Jane should still not be in any groups
  187. self.assertQuerysetEqual(
  188. self.jane.groups.all(),
  189. []
  190. )
  191. def test_m2m_through_on_self_works(self):
  192. self.assertQuerysetEqual(
  193. self.jane.friends.all(),
  194. []
  195. )
  196. Friendship.objects.create(
  197. from_friend_country=self.jane.person_country, from_friend=self.jane,
  198. to_friend_country=self.george.person_country, to_friend=self.george)
  199. self.assertQuerysetEqual(
  200. self.jane.friends.all(),
  201. ['George'], attrgetter("name")
  202. )
  203. def test_m2m_through_on_self_ignores_mismatch_columns(self):
  204. self.assertQuerysetEqual(self.jane.friends.all(), [])
  205. # Note that we use ids instead of instances. This is because instances on ForeignObject
  206. # properties will set all related field off of the given instance
  207. Friendship.objects.create(
  208. from_friend_id=self.jane.id, to_friend_id=self.george.id,
  209. to_friend_country_id=self.jane.person_country_id,
  210. from_friend_country_id=self.george.person_country_id)
  211. self.assertQuerysetEqual(self.jane.friends.all(), [])
  212. def test_prefetch_related_m2m_foward_works(self):
  213. Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
  214. Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.democrat)
  215. with self.assertNumQueries(2):
  216. members_lists = [list(g.members.all())
  217. for g in Group.objects.prefetch_related('members')]
  218. normal_members_lists = [list(g.members.all()) for g in Group.objects.all()]
  219. self.assertEqual(members_lists, normal_members_lists)
  220. def test_prefetch_related_m2m_reverse_works(self):
  221. Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia)
  222. Membership.objects.create(membership_country=self.usa, person=self.jim, group=self.democrat)
  223. with self.assertNumQueries(2):
  224. groups_lists = [list(p.groups.all()) for p in Person.objects.prefetch_related('groups')]
  225. normal_groups_lists = [list(p.groups.all()) for p in Person.objects.all()]
  226. self.assertEqual(groups_lists, normal_groups_lists)
  227. def test_translations(self):
  228. activate('fi')
  229. a1 = Article.objects.create(pub_date=datetime.date.today())
  230. at1_fi = ArticleTranslation(article=a1, lang='fi', title='Otsikko', body='Diipadaapa')
  231. at1_fi.save()
  232. at2_en = ArticleTranslation(article=a1, lang='en', title='Title', body='Lalalalala')
  233. at2_en.save()
  234. with self.assertNumQueries(1):
  235. fetched = Article.objects.select_related('active_translation').get(
  236. active_translation__title='Otsikko')
  237. self.assertTrue(fetched.active_translation.title == 'Otsikko')
  238. a2 = Article.objects.create(pub_date=datetime.date.today())
  239. at2_fi = ArticleTranslation(article=a2, lang='fi', title='Atsikko', body='Diipadaapa',
  240. abstract='dipad')
  241. at2_fi.save()
  242. a3 = Article.objects.create(pub_date=datetime.date.today())
  243. at3_en = ArticleTranslation(article=a3, lang='en', title='A title', body='lalalalala',
  244. abstract='lala')
  245. at3_en.save()
  246. # Test model initialization with active_translation field.
  247. a3 = Article(id=a3.id, pub_date=a3.pub_date, active_translation=at3_en)
  248. a3.save()
  249. self.assertEqual(
  250. list(Article.objects.filter(active_translation__abstract=None)),
  251. [a1, a3])
  252. self.assertEqual(
  253. list(Article.objects.filter(active_translation__abstract=None,
  254. active_translation__pk__isnull=False)),
  255. [a1])
  256. activate('en')
  257. self.assertEqual(
  258. list(Article.objects.filter(active_translation__abstract=None)),
  259. [a1, a2])
  260. class FormsTests(TestCase):
  261. # ForeignObjects should not have any form fields, currently the user needs
  262. # to manually deal with the foreignobject relation.
  263. class ArticleForm(forms.ModelForm):
  264. class Meta:
  265. model = Article
  266. fields = '__all__'
  267. def test_foreign_object_form(self):
  268. # A very crude test checking that the non-concrete fields do not get form fields.
  269. form = FormsTests.ArticleForm()
  270. self.assertIn('id_pub_date', form.as_table())
  271. self.assertNotIn('active_translation', form.as_table())
  272. form = FormsTests.ArticleForm(data={'pub_date': str(datetime.date.today())})
  273. self.assertTrue(form.is_valid())
  274. a = form.save()
  275. self.assertEqual(a.pub_date, datetime.date.today())
  276. form = FormsTests.ArticleForm(instance=a, data={'pub_date': '2013-01-01'})
  277. a2 = form.save()
  278. self.assertEqual(a.pk, a2.pk)
  279. self.assertEqual(a2.pub_date, datetime.date(2013, 1, 1))