tests.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. from __future__ import unicode_literals
  2. from django.db import transaction, IntegrityError
  3. from django.test import TestCase
  4. from .models import (Place, Restaurant, Waiter, ManualPrimaryKey, RelatedModel,
  5. MultiModel)
  6. class OneToOneTests(TestCase):
  7. def setUp(self):
  8. self.p1 = Place(name='Demon Dogs', address='944 W. Fullerton')
  9. self.p1.save()
  10. self.p2 = Place(name='Ace Hardware', address='1013 N. Ashland')
  11. self.p2.save()
  12. self.r = Restaurant(place=self.p1, serves_hot_dogs=True, serves_pizza=False)
  13. self.r.save()
  14. def test_getter(self):
  15. # A Restaurant can access its place.
  16. self.assertEqual(repr(self.r.place), '<Place: Demon Dogs the place>')
  17. # A Place can access its restaurant, if available.
  18. self.assertEqual(repr(self.p1.restaurant), '<Restaurant: Demon Dogs the restaurant>')
  19. # p2 doesn't have an associated restaurant.
  20. with self.assertRaisesMessage(Restaurant.DoesNotExist, 'Place has no restaurant'):
  21. self.p2.restaurant
  22. def test_setter(self):
  23. # Set the place using assignment notation. Because place is the primary
  24. # key on Restaurant, the save will create a new restaurant
  25. self.r.place = self.p2
  26. self.r.save()
  27. self.assertEqual(repr(self.p2.restaurant), '<Restaurant: Ace Hardware the restaurant>')
  28. self.assertEqual(repr(self.r.place), '<Place: Ace Hardware the place>')
  29. self.assertEqual(self.p2.pk, self.r.pk)
  30. # Set the place back again, using assignment in the reverse direction.
  31. self.p1.restaurant = self.r
  32. self.assertEqual(repr(self.p1.restaurant), '<Restaurant: Demon Dogs the restaurant>')
  33. r = Restaurant.objects.get(pk=self.p1.id)
  34. self.assertEqual(repr(r.place), '<Place: Demon Dogs the place>')
  35. def test_manager_all(self):
  36. # Restaurant.objects.all() just returns the Restaurants, not the Places.
  37. self.assertQuerysetEqual(Restaurant.objects.all(), [
  38. '<Restaurant: Demon Dogs the restaurant>',
  39. ])
  40. # Place.objects.all() returns all Places, regardless of whether they
  41. # have Restaurants.
  42. self.assertQuerysetEqual(Place.objects.order_by('name'), [
  43. '<Place: Ace Hardware the place>',
  44. '<Place: Demon Dogs the place>',
  45. ])
  46. def test_manager_get(self):
  47. def assert_get_restaurant(**params):
  48. self.assertEqual(repr(Restaurant.objects.get(**params)),
  49. '<Restaurant: Demon Dogs the restaurant>')
  50. assert_get_restaurant(place__id__exact=self.p1.pk)
  51. assert_get_restaurant(place__id=self.p1.pk)
  52. assert_get_restaurant(place__exact=self.p1.pk)
  53. assert_get_restaurant(place__exact=self.p1)
  54. assert_get_restaurant(place=self.p1.pk)
  55. assert_get_restaurant(place=self.p1)
  56. assert_get_restaurant(pk=self.p1.pk)
  57. assert_get_restaurant(place__pk__exact=self.p1.pk)
  58. assert_get_restaurant(place__pk=self.p1.pk)
  59. assert_get_restaurant(place__name__startswith="Demon")
  60. def assert_get_place(**params):
  61. self.assertEqual(repr(Place.objects.get(**params)),
  62. '<Place: Demon Dogs the place>')
  63. assert_get_place(restaurant__place__exact=self.p1.pk)
  64. assert_get_place(restaurant__place__exact=self.p1)
  65. assert_get_place(restaurant__place__pk=self.p1.pk)
  66. assert_get_place(restaurant__exact=self.p1.pk)
  67. assert_get_place(restaurant__exact=self.r)
  68. assert_get_place(restaurant__pk=self.p1.pk)
  69. assert_get_place(restaurant=self.p1.pk)
  70. assert_get_place(restaurant=self.r)
  71. assert_get_place(id__exact=self.p1.pk)
  72. assert_get_place(pk=self.p1.pk)
  73. def test_foreign_key(self):
  74. # Add a Waiter to the Restaurant.
  75. w = self.r.waiter_set.create(name='Joe')
  76. w.save()
  77. self.assertEqual(repr(w), '<Waiter: Joe the waiter at Demon Dogs the restaurant>')
  78. # Query the waiters
  79. def assert_filter_waiters(**params):
  80. self.assertQuerysetEqual(Waiter.objects.filter(**params), [
  81. '<Waiter: Joe the waiter at Demon Dogs the restaurant>'
  82. ])
  83. assert_filter_waiters(restaurant__place__exact=self.p1.pk)
  84. assert_filter_waiters(restaurant__place__exact=self.p1)
  85. assert_filter_waiters(restaurant__place__pk=self.p1.pk)
  86. assert_filter_waiters(restaurant__exact=self.p1.pk)
  87. assert_filter_waiters(restaurant__exact=self.p1)
  88. assert_filter_waiters(restaurant__pk=self.p1.pk)
  89. assert_filter_waiters(restaurant=self.p1.pk)
  90. assert_filter_waiters(restaurant=self.r)
  91. assert_filter_waiters(id__exact=self.p1.pk)
  92. assert_filter_waiters(pk=self.p1.pk)
  93. # Delete the restaurant; the waiter should also be removed
  94. r = Restaurant.objects.get(pk=self.p1.pk)
  95. r.delete()
  96. self.assertEqual(Waiter.objects.count(), 0)
  97. def test_multiple_o2o(self):
  98. # One-to-one fields still work if you create your own primary key
  99. o1 = ManualPrimaryKey(primary_key="abc123", name="primary")
  100. o1.save()
  101. o2 = RelatedModel(link=o1, name="secondary")
  102. o2.save()
  103. # You can have multiple one-to-one fields on a model, too.
  104. x1 = MultiModel(link1=self.p1, link2=o1, name="x1")
  105. x1.save()
  106. self.assertEqual(repr(o1.multimodel), '<MultiModel: Multimodel x1>')
  107. # This will fail because each one-to-one field must be unique (and
  108. # link2=o1 was used for x1, above).
  109. mm = MultiModel(link1=self.p2, link2=o1, name="x1")
  110. with self.assertRaises(IntegrityError):
  111. with transaction.atomic():
  112. mm.save()