File: one_to_one.txt

package info (click to toggle)
python-django 1.4.5-1%2Bdeb7u16
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 44,168 kB
  • sloc: python: 140,205; xml: 659; makefile: 160; sh: 145; sql: 7
file content (132 lines) | stat: -rw-r--r-- 4,154 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
########################
One-to-one relationships
########################

.. highlight:: pycon

To define a one-to-one relationship, use :ref:`ref-onetoone`.

In this example, a ``Place`` optionally can be a ``Restaurant``:

.. code-block:: python

    from django.db import models, transaction, IntegrityError

    class Place(models.Model):
        name = models.CharField(max_length=50)
        address = models.CharField(max_length=80)

        def __unicode__(self):
            return u"%s the place" % self.name

    class Restaurant(models.Model):
        place = models.OneToOneField(Place, primary_key=True)
        serves_hot_dogs = models.BooleanField()
        serves_pizza = models.BooleanField()

        def __unicode__(self):
            return u"%s the restaurant" % self.place.name

    class Waiter(models.Model):
        restaurant = models.ForeignKey(Restaurant)
        name = models.CharField(max_length=50)

        def __unicode__(self):
            return u"%s the waiter at %s" % (self.name, self.restaurant)

What follows are examples of operations that can be performed using the Python
API facilities.

Create a couple of Places::

    >>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton')
    >>> p1.save()
    >>> p2 = Place(name='Ace Hardware', address='1013 N. Ashland')
    >>> p2.save()

Create a Restaurant. Pass the ID of the "parent" object as this object's ID::

    >>> r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False)
    >>> r.save()

A Restaurant can access its place::

    >>> r.place
    <Place: Demon Dogs the place>

A Place can access its restaurant, if available::

    >>> p1.restaurant
    <Restaurant: Demon Dogs the restaurant>

p2 doesn't have an associated restaurant::

    >>> p2.restaurant
    Traceback (most recent call last):
        ...
    DoesNotExist: Restaurant matching query does not exist.

Set the place using assignment notation. Because place is the primary key on
Restaurant, the save will create a new restaurant::

    >>> r.place = p2
    >>> r.save()
    >>> p2.restaurant
    <Restaurant: Ace Hardware the restaurant>
    >>> r.place
    <Place: Ace Hardware the place>

Set the place back again, using assignment in the reverse direction::

    >>> p1.restaurant = r
    >>> p1.restaurant
    <Restaurant: Demon Dogs the restaurant>

Restaurant.objects.all() just returns the Restaurants, not the Places.  Note
that there are two restaurants - Ace Hardware the Restaurant was created in the
call to r.place = p2::

    >>> Restaurant.objects.all()
    [<Restaurant: Demon Dogs the restaurant>, <Restaurant: Ace Hardware the restaurant>]

Place.objects.all() returns all Places, regardless of whether they have
Restaurants::

    >>> Place.objects.order_by('name')
    [<Place: Ace Hardware the place>, <Place: Demon Dogs the place>]

You can query the models using :ref:`lookups across relationships <lookups-that-span-relationships>`::

    >>> Restaurant.objects.get(place=p1)
    <Restaurant: Demon Dogs the restaurant>
    >>> Restaurant.objects.get(place__pk=1)
    <Restaurant: Demon Dogs the restaurant>
    >>> Restaurant.objects.filter(place__name__startswith="Demon")
    [<Restaurant: Demon Dogs the restaurant>]
    >>> Restaurant.objects.exclude(place__address__contains="Ashland")
    [<Restaurant: Demon Dogs the restaurant>]

This of course works in reverse::

    >>> Place.objects.get(pk=1)
    <Place: Demon Dogs the place>
    >>> Place.objects.get(restaurant__place__exact=p1)
    <Place: Demon Dogs the place>
    >>> Place.objects.get(restaurant=r)
    <Place: Demon Dogs the place>
    >>> Place.objects.get(restaurant__place__name__startswith="Demon")
    <Place: Demon Dogs the place>

Add a Waiter to the Restaurant::

    >>> w = r.waiter_set.create(name='Joe')
    >>> w.save()
    >>> w
    <Waiter: Joe the waiter at Demon Dogs the restaurant>

Query the waiters::

    >>> Waiter.objects.filter(restaurant__place=p1)
    [<Waiter: Joe the waiter at Demon Dogs the restaurant>]
    >>> Waiter.objects.filter(restaurant__place__name__startswith="Demon")
    [<Waiter: Joe the waiter at Demon Dogs the restaurant>]