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