~ubuntu-branches/ubuntu/quantal/python-django/quantal

« back to all changes in this revision

Viewing changes to tests/modeltests/one_to_one/models.py

  • Committer: Bazaar Package Importer
  • Author(s): Chris Lamb
  • Date: 2009-07-29 11:26:28 UTC
  • mfrom: (1.1.8 upstream) (4.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20090729112628-pg09ino8sz0sj21t
Tags: 1.1-1
* New upstream release.
* Merge from experimental:
  - Ship FastCGI initscript and /etc/default file in python-django's examples
    directory (Closes: #538863)
  - Drop "05_10539-sphinx06-compatibility.diff"; it has been applied
    upstream.
  - Bump Standards-Version to 3.8.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
2
10. One-to-one relationships
 
3
 
 
4
To define a one-to-one relationship, use ``OneToOneField()``.
 
5
 
 
6
In this example, a ``Place`` optionally can be a ``Restaurant``.
 
7
"""
 
8
 
 
9
from django.db import models, transaction, IntegrityError
 
10
 
 
11
class Place(models.Model):
 
12
    name = models.CharField(max_length=50)
 
13
    address = models.CharField(max_length=80)
 
14
 
 
15
    def __unicode__(self):
 
16
        return u"%s the place" % self.name
 
17
 
 
18
class Restaurant(models.Model):
 
19
    place = models.OneToOneField(Place, primary_key=True)
 
20
    serves_hot_dogs = models.BooleanField()
 
21
    serves_pizza = models.BooleanField()
 
22
 
 
23
    def __unicode__(self):
 
24
        return u"%s the restaurant" % self.place.name
 
25
 
 
26
class Waiter(models.Model):
 
27
    restaurant = models.ForeignKey(Restaurant)
 
28
    name = models.CharField(max_length=50)
 
29
 
 
30
    def __unicode__(self):
 
31
        return u"%s the waiter at %s" % (self.name, self.restaurant)
 
32
 
 
33
class ManualPrimaryKey(models.Model):
 
34
    primary_key = models.CharField(max_length=10, primary_key=True)
 
35
    name = models.CharField(max_length = 50)
 
36
 
 
37
class RelatedModel(models.Model):
 
38
    link = models.OneToOneField(ManualPrimaryKey)
 
39
    name = models.CharField(max_length = 50)
 
40
 
 
41
class MultiModel(models.Model):
 
42
    link1 = models.OneToOneField(Place)
 
43
    link2 = models.OneToOneField(ManualPrimaryKey)
 
44
    name = models.CharField(max_length=50)
 
45
 
 
46
    def __unicode__(self):
 
47
        return u"Multimodel %s" % self.name
 
48
 
 
49
__test__ = {'API_TESTS':"""
 
50
# Create a couple of Places.
 
51
>>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton')
 
52
>>> p1.save()
 
53
>>> p2 = Place(name='Ace Hardware', address='1013 N. Ashland')
 
54
>>> p2.save()
 
55
 
 
56
# Create a Restaurant. Pass the ID of the "parent" object as this object's ID.
 
57
>>> r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False)
 
58
>>> r.save()
 
59
 
 
60
# A Restaurant can access its place.
 
61
>>> r.place
 
62
<Place: Demon Dogs the place>
 
63
 
 
64
# A Place can access its restaurant, if available.
 
65
>>> p1.restaurant
 
66
<Restaurant: Demon Dogs the restaurant>
 
67
 
 
68
# p2 doesn't have an associated restaurant.
 
69
>>> p2.restaurant
 
70
Traceback (most recent call last):
 
71
    ...
 
72
DoesNotExist: Restaurant matching query does not exist.
 
73
 
 
74
# Set the place using assignment notation. Because place is the primary key on
 
75
# Restaurant, the save will create a new restaurant
 
76
>>> r.place = p2
 
77
>>> r.save()
 
78
>>> p2.restaurant
 
79
<Restaurant: Ace Hardware the restaurant>
 
80
>>> r.place
 
81
<Place: Ace Hardware the place>
 
82
>>> p2.id
 
83
2
 
84
 
 
85
# Set the place back again, using assignment in the reverse direction.
 
86
>>> p1.restaurant = r
 
87
>>> p1.restaurant
 
88
<Restaurant: Demon Dogs the restaurant>
 
89
 
 
90
>>> r = Restaurant.objects.get(pk=1)
 
91
>>> r.place
 
92
<Place: Demon Dogs the place>
 
93
 
 
94
# Restaurant.objects.all() just returns the Restaurants, not the Places.
 
95
# Note that there are two restaurants - Ace Hardware the Restaurant was created
 
96
# in the call to r.place = p2.
 
97
>>> Restaurant.objects.all()
 
98
[<Restaurant: Demon Dogs the restaurant>, <Restaurant: Ace Hardware the restaurant>]
 
99
 
 
100
# Place.objects.all() returns all Places, regardless of whether they have
 
101
# Restaurants.
 
102
>>> Place.objects.order_by('name')
 
103
[<Place: Ace Hardware the place>, <Place: Demon Dogs the place>]
 
104
 
 
105
>>> Restaurant.objects.get(place__id__exact=1)
 
106
<Restaurant: Demon Dogs the restaurant>
 
107
>>> Restaurant.objects.get(pk=1)
 
108
<Restaurant: Demon Dogs the restaurant>
 
109
>>> Restaurant.objects.get(place__exact=1)
 
110
<Restaurant: Demon Dogs the restaurant>
 
111
>>> Restaurant.objects.get(place__exact=p1)
 
112
<Restaurant: Demon Dogs the restaurant>
 
113
>>> Restaurant.objects.get(place=1)
 
114
<Restaurant: Demon Dogs the restaurant>
 
115
>>> Restaurant.objects.get(place=p1)
 
116
<Restaurant: Demon Dogs the restaurant>
 
117
>>> Restaurant.objects.get(place__pk=1)
 
118
<Restaurant: Demon Dogs the restaurant>
 
119
>>> Restaurant.objects.get(place__name__startswith="Demon")
 
120
<Restaurant: Demon Dogs the restaurant>
 
121
 
 
122
>>> Place.objects.get(id__exact=1)
 
123
<Place: Demon Dogs the place>
 
124
>>> Place.objects.get(pk=1)
 
125
<Place: Demon Dogs the place>
 
126
>>> Place.objects.get(restaurant__place__exact=1)
 
127
<Place: Demon Dogs the place>
 
128
>>> Place.objects.get(restaurant__place__exact=p1)
 
129
<Place: Demon Dogs the place>
 
130
>>> Place.objects.get(restaurant__pk=1)
 
131
<Place: Demon Dogs the place>
 
132
>>> Place.objects.get(restaurant=1)
 
133
<Place: Demon Dogs the place>
 
134
>>> Place.objects.get(restaurant=r)
 
135
<Place: Demon Dogs the place>
 
136
>>> Place.objects.get(restaurant__exact=1)
 
137
<Place: Demon Dogs the place>
 
138
>>> Place.objects.get(restaurant__exact=r)
 
139
<Place: Demon Dogs the place>
 
140
 
 
141
# Add a Waiter to the Restaurant.
 
142
>>> w = r.waiter_set.create(name='Joe')
 
143
>>> w.save()
 
144
>>> w
 
145
<Waiter: Joe the waiter at Demon Dogs the restaurant>
 
146
 
 
147
# Query the waiters
 
148
>>> Waiter.objects.filter(restaurant__place__pk=1)
 
149
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
 
150
>>> Waiter.objects.filter(restaurant__place__exact=1)
 
151
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
 
152
>>> Waiter.objects.filter(restaurant__place__exact=p1)
 
153
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
 
154
>>> Waiter.objects.filter(restaurant__pk=1)
 
155
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
 
156
>>> Waiter.objects.filter(id__exact=1)
 
157
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
 
158
>>> Waiter.objects.filter(pk=1)
 
159
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
 
160
>>> Waiter.objects.filter(restaurant=1)
 
161
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
 
162
>>> Waiter.objects.filter(restaurant=r)
 
163
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
 
164
 
 
165
# Delete the restaurant; the waiter should also be removed
 
166
>>> r = Restaurant.objects.get(pk=1)
 
167
>>> r.delete()
 
168
 
 
169
# One-to-one fields still work if you create your own primary key
 
170
>>> o1 = ManualPrimaryKey(primary_key="abc123", name="primary")
 
171
>>> o1.save()
 
172
>>> o2 = RelatedModel(link=o1, name="secondary")
 
173
>>> o2.save()
 
174
 
 
175
# You can have multiple one-to-one fields on a model, too.
 
176
>>> x1 = MultiModel(link1=p1, link2=o1, name="x1")
 
177
>>> x1.save()
 
178
>>> o1.multimodel
 
179
<MultiModel: Multimodel x1>
 
180
 
 
181
# This will fail because each one-to-one field must be unique (and link2=o1 was
 
182
# used for x1, above).
 
183
>>> sid = transaction.savepoint()
 
184
>>> try:
 
185
...     MultiModel(link1=p2, link2=o1, name="x1").save()
 
186
... except Exception, e:
 
187
...     if isinstance(e, IntegrityError):
 
188
...         print "Pass"
 
189
...     else:
 
190
...         print "Fail with %s" % type(e)
 
191
Pass
 
192
>>> transaction.savepoint_rollback(sid)
 
193
 
 
194
"""}