| 1 |
from django.db import models |
|---|
| 2 |
|
|---|
| 3 |
class Place(models.Model): |
|---|
| 4 |
name = models.CharField(max_length=50) |
|---|
| 5 |
address = models.CharField(max_length=80) |
|---|
| 6 |
|
|---|
| 7 |
def __unicode__(self): |
|---|
| 8 |
return u"%s the place" % self.name |
|---|
| 9 |
|
|---|
| 10 |
class Restaurant(models.Model): |
|---|
| 11 |
place = models.OneToOneField(Place) |
|---|
| 12 |
serves_hot_dogs = models.BooleanField() |
|---|
| 13 |
serves_pizza = models.BooleanField() |
|---|
| 14 |
|
|---|
| 15 |
def __unicode__(self): |
|---|
| 16 |
return u"%s the restaurant" % self.place.name |
|---|
| 17 |
|
|---|
| 18 |
class Bar(models.Model): |
|---|
| 19 |
place = models.OneToOneField(Place) |
|---|
| 20 |
serves_cocktails = models.BooleanField() |
|---|
| 21 |
|
|---|
| 22 |
def __unicode__(self): |
|---|
| 23 |
return u"%s the bar" % self.place.name |
|---|
| 24 |
|
|---|
| 25 |
class UndergroundBar(models.Model): |
|---|
| 26 |
place = models.OneToOneField(Place, null=True) |
|---|
| 27 |
serves_cocktails = models.BooleanField() |
|---|
| 28 |
|
|---|
| 29 |
class Favorites(models.Model): |
|---|
| 30 |
name = models.CharField(max_length = 50) |
|---|
| 31 |
restaurants = models.ManyToManyField(Restaurant) |
|---|
| 32 |
|
|---|
| 33 |
def __unicode__(self): |
|---|
| 34 |
return u"Favorites for %s" % self.name |
|---|
| 35 |
|
|---|
| 36 |
__test__ = {'API_TESTS':""" |
|---|
| 37 |
# Regression test for #1064 and #1506: Check that we create models via the m2m |
|---|
| 38 |
# relation if the remote model has a OneToOneField. |
|---|
| 39 |
>>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton') |
|---|
| 40 |
>>> p1.save() |
|---|
| 41 |
>>> r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False) |
|---|
| 42 |
>>> r.save() |
|---|
| 43 |
>>> f = Favorites(name = 'Fred') |
|---|
| 44 |
>>> f.save() |
|---|
| 45 |
>>> f.restaurants = [r] |
|---|
| 46 |
>>> f.restaurants.all() |
|---|
| 47 |
[<Restaurant: Demon Dogs the restaurant>] |
|---|
| 48 |
|
|---|
| 49 |
# Regression test for #7173: Check that the name of the cache for the |
|---|
| 50 |
# reverse object is correct. |
|---|
| 51 |
>>> b = Bar(place=p1, serves_cocktails=False) |
|---|
| 52 |
>>> b.save() |
|---|
| 53 |
>>> p1.restaurant |
|---|
| 54 |
<Restaurant: Demon Dogs the restaurant> |
|---|
| 55 |
>>> p1.bar |
|---|
| 56 |
<Bar: Demon Dogs the bar> |
|---|
| 57 |
|
|---|
| 58 |
# |
|---|
| 59 |
# Regression test for #6886 (the related-object cache) |
|---|
| 60 |
# |
|---|
| 61 |
|
|---|
| 62 |
# Look up the objects again so that we get "fresh" objects |
|---|
| 63 |
>>> p = Place.objects.get(name="Demon Dogs") |
|---|
| 64 |
>>> r = p.restaurant |
|---|
| 65 |
|
|---|
| 66 |
# Accessing the related object again returns the exactly same object |
|---|
| 67 |
>>> p.restaurant is r |
|---|
| 68 |
True |
|---|
| 69 |
|
|---|
| 70 |
# But if we kill the cache, we get a new object |
|---|
| 71 |
>>> del p._restaurant_cache |
|---|
| 72 |
>>> p.restaurant is r |
|---|
| 73 |
False |
|---|
| 74 |
|
|---|
| 75 |
# Reassigning the Restaurant object results in an immediate cache update |
|---|
| 76 |
# We can't use a new Restaurant because that'll violate one-to-one, but |
|---|
| 77 |
# with a new *instance* the is test below will fail if #6886 regresses. |
|---|
| 78 |
>>> r2 = Restaurant.objects.get(pk=r.pk) |
|---|
| 79 |
>>> p.restaurant = r2 |
|---|
| 80 |
>>> p.restaurant is r2 |
|---|
| 81 |
True |
|---|
| 82 |
|
|---|
| 83 |
# Assigning None succeeds if field is null=True. |
|---|
| 84 |
>>> ug_bar = UndergroundBar.objects.create(place=p, serves_cocktails=False) |
|---|
| 85 |
>>> ug_bar.place = None |
|---|
| 86 |
>>> ug_bar.place is None |
|---|
| 87 |
True |
|---|
| 88 |
|
|---|
| 89 |
# Assigning None fails: Place.restaurant is null=False |
|---|
| 90 |
>>> p.restaurant = None |
|---|
| 91 |
Traceback (most recent call last): |
|---|
| 92 |
... |
|---|
| 93 |
ValueError: Cannot assign None: "Place.restaurant" does not allow null values. |
|---|
| 94 |
|
|---|
| 95 |
# You also can't assign an object of the wrong type here |
|---|
| 96 |
>>> p.restaurant = p |
|---|
| 97 |
Traceback (most recent call last): |
|---|
| 98 |
... |
|---|
| 99 |
ValueError: Cannot assign "<Place: Demon Dogs the place>": "Place.restaurant" must be a "Restaurant" instance. |
|---|
| 100 |
|
|---|
| 101 |
# Creation using keyword argument should cache the related object. |
|---|
| 102 |
>>> p = Place.objects.get(name="Demon Dogs") |
|---|
| 103 |
>>> r = Restaurant(place=p) |
|---|
| 104 |
>>> r.place is p |
|---|
| 105 |
True |
|---|
| 106 |
|
|---|
| 107 |
# Creation using keyword argument and unsaved related instance (#8070). |
|---|
| 108 |
>>> p = Place() |
|---|
| 109 |
>>> r = Restaurant(place=p) |
|---|
| 110 |
>>> r.place is p |
|---|
| 111 |
True |
|---|
| 112 |
|
|---|
| 113 |
# Creation using attname keyword argument and an id will cause the related |
|---|
| 114 |
# object to be fetched. |
|---|
| 115 |
>>> p = Place.objects.get(name="Demon Dogs") |
|---|
| 116 |
>>> r = Restaurant(place_id=p.id) |
|---|
| 117 |
>>> r.place is p |
|---|
| 118 |
False |
|---|
| 119 |
>>> r.place == p |
|---|
| 120 |
True |
|---|
| 121 |
|
|---|
| 122 |
"""} |
|---|