Ticket #17605: 17605-2.diff
File 17605-2.diff, 33.7 KB (added by , 13 years ago) |
---|
-
new file docs/topics/db/examples/many_to_many.txt
diff --git a/docs/topics/db/examples/many_to_many.txt b/docs/topics/db/examples/many_to_many.txt new file mode 100644
- + 1 ########################## 2 Many-to-many relationships 3 ########################## 4 5 To define a many-to-many relationship, use ``ManyToManyField()``. 6 7 In this example, an ``Article`` can be published in multiple ``Publication`` 8 objects, and a ``Publication`` has multiple ``Article`` objects:: 9 10 from django.db import models 11 12 class Publication(models.Model): 13 title = models.CharField(max_length=30) 14 15 def __unicode__(self): 16 return self.title 17 18 class Meta: 19 ordering = ('title',) 20 21 class Article(models.Model): 22 headline = models.CharField(max_length=100) 23 publications = models.ManyToManyField(Publication) 24 25 def __unicode__(self): 26 return self.headline 27 28 class Meta: 29 ordering = ('headline',) 30 31 What follows are examples of operations that can be performed using the Python 32 API facilities:: 33 34 >>> # Create a couple of Publications. 35 >>> p1 = Publication(id=None, title='The Python Journal') 36 >>> p1.save() 37 >>> p2 = Publication(id=None, title='Science News') 38 >>> p2.save() 39 >>> p3 = Publication(id=None, title='Science Weekly') 40 >>> p3.save() 41 42 # Create an Article. 43 >>> a1 = Article(id=None, headline='Django lets you build Web apps easily') 44 45 # You can't associate it with a Publication until it's been saved. 46 >>> a1.publications.add(p1) 47 Traceback (most recent call last): 48 ... 49 ValueError: 'Article' instance needs to have a primary key value before a many-to-many relationship can be used. 50 51 # Save it! 52 >>> a1.save() 53 54 # Associate the Article with a Publication. 55 >>> a1.publications.add(p1) 56 57 # Create another Article, and set it to appear in both 58 # Publications. 59 >>> a2 = Article(id=None, headline='NASA uses Python') 60 >>> a2.save() 61 >>> a2.publications.add(p1, p2) 62 >>> a2.publications.add(p3) 63 64 # Adding a second time is OK 65 >>> a2.publications.add(p3) 66 67 # Adding an object of the wrong type raises TypeError 68 >>> a2.publications.add(a1) 69 Traceback (most recent call last): 70 ... 71 TypeError: 'Publication' instance expected 72 73 # Add a Publication directly via publications.add by using 74 # keyword arguments. 75 >>> new_publication = a2.publications.create(title='Highlights for Children') 76 77 # Article objects have access to their related Publication 78 # objects. 79 >>> a1.publications.all() 80 [<Publication: The Python Journal>] 81 >>> a2.publications.all() 82 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] 83 84 # Publication objects have access to their related Article 85 # objects. 86 >>> p2.article_set.all() 87 [<Article: NASA uses Python>] 88 >>> p1.article_set.all() 89 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] 90 >>> Publication.objects.get(id=4).article_set.all() 91 [<Article: NASA uses Python>] 92 93 # We can perform kwarg queries across m2m relationships 94 >>> Article.objects.filter(publications__id__exact=1) 95 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] 96 >>> Article.objects.filter(publications__pk=1) 97 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] 98 >>> Article.objects.filter(publications=1) 99 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] 100 >>> Article.objects.filter(publications=p1) 101 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] 102 103 >>> Article.objects.filter(publications__title__startswith="Science") 104 [<Article: NASA uses Python>, <Article: NASA uses Python>] 105 106 >>> Article.objects.filter(publications__title__startswith="Science").distinct() 107 [<Article: NASA uses Python>] 108 109 # The count() function respects distinct() as well. 110 >>> Article.objects.filter(publications__title__startswith="Science").count() 111 2 112 113 >>> Article.objects.filter(publications__title__startswith="Science").distinct().count() 114 1 115 116 >>> Article.objects.filter(publications__in=[1,2]).distinct() 117 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] 118 >>> Article.objects.filter(publications__in=[1,p2]).distinct() 119 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] 120 >>> Article.objects.filter(publications__in=[p1,p2]).distinct() 121 [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] 122 123 # Reverse m2m queries are supported (i.e., starting at the table 124 # that doesn't have a ManyToManyField). 125 >>> Publication.objects.filter(id__exact=1) 126 [<Publication: The Python Journal>] 127 >>> Publication.objects.filter(pk=1) 128 [<Publication: The Python Journal>] 129 130 >>> Publication.objects.filter(article__headline__startswith="NASA") 131 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] 132 133 >>> Publication.objects.filter(article__id__exact=1) 134 [<Publication: The Python Journal>] 135 >>> Publication.objects.filter(article__pk=1) 136 [<Publication: The Python Journal>] 137 >>> Publication.objects.filter(article=1) 138 [<Publication: The Python Journal>] 139 >>> Publication.objects.filter(article=a1) 140 [<Publication: The Python Journal>] 141 142 >>> Publication.objects.filter(article__in=[1,2]).distinct() 143 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] 144 >>> Publication.objects.filter(article__in=[1,a2]).distinct() 145 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] 146 >>> Publication.objects.filter(article__in=[a1,a2]).distinct() 147 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] 148 149 # Excluding a related item works as you would expect, too 150 # (although the SQL involved is a little complex). 151 >>> Article.objects.exclude(publications=p2) 152 [<Article: Django lets you build Web apps easily>] 153 154 # If we delete a Publication, its Articles won't be able to 155 # access it. 156 >>> p1.delete() 157 >>> Publication.objects.all() 158 [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>] 159 >>> a1 = Article.objects.get(pk=1) 160 >>> a1.publications.all() 161 [] 162 163 # If we delete an Article, its Publications won't be able to 164 # access it. 165 >>> a2.delete() 166 >>> Article.objects.all() 167 [<Article: Django lets you build Web apps easily>] 168 >>> p2.article_set.all() 169 [] 170 171 # Adding via the 'other' end of an m2m 172 >>> a4 = Article(headline='NASA finds intelligent life on Earth') 173 >>> a4.save() 174 >>> p2.article_set.add(a4) 175 >>> p2.article_set.all() 176 [<Article: NASA finds intelligent life on Earth>] 177 >>> a4.publications.all() 178 [<Publication: Science News>] 179 180 # Adding via the other end using keywords 181 >>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders') 182 >>> p2.article_set.all() 183 [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>] 184 >>> a5 = p2.article_set.all()[1] 185 >>> a5.publications.all() 186 [<Publication: Science News>] 187 188 # Removing publication from an article: 189 >>> a4.publications.remove(p2) 190 >>> p2.article_set.all() 191 [<Article: Oxygen-free diet works wonders>] 192 >>> a4.publications.all() 193 [] 194 195 # And from the other end 196 >>> p2.article_set.remove(a5) 197 >>> p2.article_set.all() 198 [] 199 >>> a5.publications.all() 200 [] 201 202 # Relation sets can be assigned. Assignment clears any existing set members 203 >>> p2.article_set = [a4, a5] 204 >>> p2.article_set.all() 205 [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>] 206 >>> a4.publications.all() 207 [<Publication: Science News>] 208 >>> a4.publications = [p3] 209 >>> p2.article_set.all() 210 [<Article: Oxygen-free diet works wonders>] 211 >>> a4.publications.all() 212 [<Publication: Science Weekly>] 213 214 # Relation sets can be cleared: 215 >>> p2.article_set.clear() 216 >>> p2.article_set.all() 217 [] 218 >>> a4.publications.all() 219 [<Publication: Science Weekly>] 220 221 # And you can clear from the other end 222 >>> p2.article_set.add(a4, a5) 223 >>> p2.article_set.all() 224 [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>] 225 >>> a4.publications.all() 226 [<Publication: Science News>, <Publication: Science Weekly>] 227 >>> a4.publications.clear() 228 >>> a4.publications.all() 229 [] 230 >>> p2.article_set.all() 231 [<Article: Oxygen-free diet works wonders>] 232 233 # Relation sets can also be set using primary key values 234 >>> p2.article_set = [a4.id, a5.id] 235 >>> p2.article_set.all() 236 [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>] 237 >>> a4.publications.all() 238 [<Publication: Science News>] 239 >>> a4.publications = [p3.id] 240 >>> p2.article_set.all() 241 [<Article: Oxygen-free diet works wonders>] 242 >>> a4.publications.all() 243 [<Publication: Science Weekly>] 244 245 # Recreate the article and Publication we have deleted. 246 >>> p1 = Publication(id=None, title='The Python Journal') 247 >>> p1.save() 248 >>> a2 = Article(id=None, headline='NASA uses Python') 249 >>> a2.save() 250 >>> a2.publications.add(p1, p2, p3) 251 252 # Bulk delete some Publications - references to deleted 253 # publications should go 254 >>> Publication.objects.filter(title__startswith='Science').delete() 255 >>> Publication.objects.all() 256 [<Publication: Highlights for Children>, <Publication: The Python Journal>] 257 >>> Article.objects.all() 258 [<Article: Django lets you build Web apps easily>, <Article: NASA finds intelligent life on Earth>, <Article: NASA uses Python>, <Article: Oxygen-free diet works wonders>] 259 >>> a2.publications.all() 260 [<Publication: The Python Journal>] 261 262 # Bulk delete some articles - references to deleted objects 263 # should go 264 >>> q = Article.objects.filter(headline__startswith='Django') 265 >>> print q 266 [<Article: Django lets you build Web apps easily>] 267 >>> q.delete() 268 269 # After the delete, the QuerySet cache needs to be cleared, and 270 # the referenced objects should be gone 271 >>> print q 272 [] 273 >>> p1.article_set.all() 274 [<Article: NASA uses Python>] 275 276 # An alternate to calling clear() is to assign the empty set 277 >>> p1.article_set = [] 278 >>> p1.article_set.all() 279 [] 280 281 >>> a2.publications = [p1, new_publication] 282 >>> a2.publications.all() 283 [<Publication: Highlights for Children>, <Publication: The Python Journal>] 284 >>> a2.publications = [] 285 >>> a2.publications.all() 286 [] -
new file docs/topics/db/examples/many_to_one.txt
diff --git a/docs/topics/db/examples/many_to_one.txt b/docs/topics/db/examples/many_to_one.txt new file mode 100644
- + 1 ######################### 2 Many-to-one relationships 3 ######################### 4 5 To define a many-to-one relationship, use ``ForeignKey()``. 6 7 :: 8 9 from django.db import models 10 11 class Reporter(models.Model): 12 first_name = models.CharField(max_length=30) 13 last_name = models.CharField(max_length=30) 14 email = models.EmailField() 15 16 def __unicode__(self): 17 return u"%s %s" % (self.first_name, self.last_name) 18 19 class Article(models.Model): 20 headline = models.CharField(max_length=100) 21 pub_date = models.DateField() 22 reporter = models.ForeignKey(Reporter) 23 24 def __unicode__(self): 25 return self.headline 26 27 class Meta: 28 ordering = ('headline',) 29 30 What follows are examples of operations that can be performed using the Python 31 API facilities:: 32 33 >>> # Create a few Reporters. 34 >>> r = Reporter(first_name='John', last_name='Smith', email='john@example.com') 35 >>> r.save() 36 37 >>> r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com') 38 >>> r2.save() 39 40 # Create an Article. 41 >>> from datetime import datetime 42 >>> a = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter=r) 43 >>> a.save() 44 45 >>> a.reporter.id 46 1 47 48 >>> a.reporter 49 <Reporter: John Smith> 50 51 # Article objects have access to their related Reporter objects. 52 >>> r = a.reporter 53 54 # These are strings instead of unicode strings because that's what was used 55 # in the creation of this reporter (and we haven't refreshed the data from 56 # the database, which always returns unicode strings). 57 >>> r.first_name, r.last_name 58 ('John', 'Smith') 59 60 # Create an Article via the Reporter object. 61 >>> new_article = r.article_set.create(headline="John's second story", pub_date=datetime(2005, 7, 29)) 62 >>> new_article 63 <Article: John's second story> 64 >>> new_article.reporter.id 65 1 66 67 # Create a new article, and add it to the article set. 68 >>> new_article2 = Article(headline="Paul's story", pub_date=datetime(2006, 1, 17)) 69 >>> r.article_set.add(new_article2) 70 >>> new_article2.reporter.id 71 1 72 >>> r.article_set.all() 73 [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] 74 75 # Add the same article to a different article set - check that it moves. 76 >>> r2.article_set.add(new_article2) 77 >>> new_article2.reporter.id 78 2 79 80 # Adding an object of the wrong type raises TypeError 81 >>> r.article_set.add(r2) 82 Traceback (most recent call last): 83 ... 84 TypeError: 'Article' instance expected 85 86 >>> r.article_set.all() 87 [<Article: John's second story>, <Article: This is a test>] 88 >>> r2.article_set.all() 89 [<Article: Paul's story>] 90 91 # Assign the article to the reporter directly using the descriptor 92 >>> new_article2.reporter = r 93 >>> new_article2.save() 94 >>> new_article2.reporter 95 <Reporter: John Smith> 96 >>> new_article2.reporter.id 97 1 98 >>> r.article_set.all() 99 [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] 100 >>> r2.article_set.all() 101 [] 102 103 # Set the article back again using set descriptor. 104 >>> r2.article_set = [new_article, new_article2] 105 >>> r.article_set.all() 106 [<Article: This is a test>] 107 >>> r2.article_set.all() 108 [<Article: John's second story>, <Article: Paul's story>] 109 110 # Funny case - assignment notation can only go so far; because the 111 # ForeignKey cannot be null, existing members of the set must remain 112 >>> r.article_set = [new_article] 113 >>> r.article_set.all() 114 [<Article: John's second story>, <Article: This is a test>] 115 >>> r2.article_set.all() 116 [<Article: Paul's story>] 117 118 # Reporter cannot be null - there should not be a clear or remove method 119 >>> hasattr(r2.article_set, 'remove') 120 False 121 >>> hasattr(r2.article_set, 'clear') 122 False 123 124 # Reporter objects have access to their related Article objects. 125 >>> r.article_set.all() 126 [<Article: John's second story>, <Article: This is a test>] 127 128 >>> r.article_set.filter(headline__startswith='This') 129 [<Article: This is a test>] 130 131 >>> r.article_set.count() 132 2 133 134 >>> r2.article_set.count() 135 1 136 137 # Get articles by id 138 >>> Article.objects.filter(id__exact=1) 139 [<Article: This is a test>] 140 >>> Article.objects.filter(pk=1) 141 [<Article: This is a test>] 142 143 # Query on an article property 144 >>> Article.objects.filter(headline__startswith='This') 145 [<Article: This is a test>] 146 147 # The API automatically follows relationships as far as you need. 148 # Use double underscores to separate relationships. 149 # This works as many levels deep as you want. There's no limit. 150 # Find all Articles for any Reporter whose first name is "John". 151 >>> Article.objects.filter(reporter__first_name__exact='John') 152 [<Article: John's second story>, <Article: This is a test>] 153 154 # Check that implied __exact also works 155 >>> Article.objects.filter(reporter__first_name='John') 156 [<Article: John's second story>, <Article: This is a test>] 157 158 # Query twice over the related field. 159 >>> Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith') 160 [<Article: John's second story>, <Article: This is a test>] 161 162 # The underlying query only makes one join when a related table is 163 # referenced twice. 164 >>> queryset = Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith') 165 >>> sql = queryset.query.get_compiler(queryset.db).as_sql()[0] 166 >>> sql.count('INNER JOIN') 167 1 168 169 # The automatically joined table has a predictable name. 170 >>> Article.objects.filter(reporter__first_name__exact='John').extra(where=["many_to_one_reporter.last_name='Smith'"]) 171 [<Article: John's second story>, <Article: This is a test>] 172 173 # And should work fine with the unicode that comes out of 174 # forms.Form.cleaned_data 175 >>> Article.objects.filter(reporter__first_name__exact='John').extra(where=["many_to_one_reporter.last_name='%s'" % u'Smith']) 176 [<Article: John's second story>, <Article: This is a test>] 177 178 # Find all Articles for the Reporter whose ID is 1. 179 # Use direct ID check, pk check, and object comparison 180 >>> Article.objects.filter(reporter__id__exact=1) 181 [<Article: John's second story>, <Article: This is a test>] 182 >>> Article.objects.filter(reporter__pk=1) 183 [<Article: John's second story>, <Article: This is a test>] 184 >>> Article.objects.filter(reporter=1) 185 [<Article: John's second story>, <Article: This is a test>] 186 >>> Article.objects.filter(reporter=r) 187 [<Article: John's second story>, <Article: This is a test>] 188 189 >>> Article.objects.filter(reporter__in=[1,2]).distinct() 190 [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] 191 >>> Article.objects.filter(reporter__in=[r,r2]).distinct() 192 [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] 193 194 # You can also use a queryset instead of a literal list of instances. 195 # The queryset must be reduced to a list of values using values(), 196 # then converted into a query 197 >>> Article.objects.filter(reporter__in=Reporter.objects.filter(first_name='John').values('pk').query).distinct() 198 [<Article: John's second story>, <Article: This is a test>] 199 200 # You need two underscores between "reporter" and "id" -- not one. 201 >>> Article.objects.filter(reporter_id__exact=1) 202 Traceback (most recent call last): 203 ... 204 FieldError: Cannot resolve keyword 'reporter_id' into field. Choices are: headline, id, pub_date, reporter 205 206 # You need to specify a comparison clause 207 >>> Article.objects.filter(reporter_id=1) 208 Traceback (most recent call last): 209 ... 210 FieldError: Cannot resolve keyword 'reporter_id' into field. Choices are: headline, id, pub_date, reporter 211 212 # You can also instantiate an Article by passing 213 # the Reporter's ID instead of a Reporter object. 214 >>> a3 = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter_id=r.id) 215 >>> a3.save() 216 >>> a3.reporter.id 217 1 218 >>> a3.reporter 219 <Reporter: John Smith> 220 221 # Similarly, the reporter ID can be a string. 222 >>> a4 = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter_id="1") 223 >>> a4.save() 224 >>> a4.reporter 225 <Reporter: John Smith> 226 227 # Reporters can be queried 228 >>> Reporter.objects.filter(id__exact=1) 229 [<Reporter: John Smith>] 230 >>> Reporter.objects.filter(pk=1) 231 [<Reporter: John Smith>] 232 >>> Reporter.objects.filter(first_name__startswith='John') 233 [<Reporter: John Smith>] 234 235 # Reporters can query in opposite direction of ForeignKey definition 236 >>> Reporter.objects.filter(article__id__exact=1) 237 [<Reporter: John Smith>] 238 >>> Reporter.objects.filter(article__pk=1) 239 [<Reporter: John Smith>] 240 >>> Reporter.objects.filter(article=1) 241 [<Reporter: John Smith>] 242 >>> Reporter.objects.filter(article=a) 243 [<Reporter: John Smith>] 244 245 >>> Reporter.objects.filter(article__in=[1,4]).distinct() 246 [<Reporter: John Smith>] 247 >>> Reporter.objects.filter(article__in=[1,a3]).distinct() 248 [<Reporter: John Smith>] 249 >>> Reporter.objects.filter(article__in=[a,a3]).distinct() 250 [<Reporter: John Smith>] 251 252 >>> Reporter.objects.filter(article__headline__startswith='This') 253 [<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>] 254 >>> Reporter.objects.filter(article__headline__startswith='This').distinct() 255 [<Reporter: John Smith>] 256 257 # Counting in the opposite direction works in conjunction with distinct() 258 >>> Reporter.objects.filter(article__headline__startswith='This').count() 259 3 260 >>> Reporter.objects.filter(article__headline__startswith='This').distinct().count() 261 1 262 263 # Queries can go round in circles. 264 >>> Reporter.objects.filter(article__reporter__first_name__startswith='John') 265 [<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>] 266 >>> Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct() 267 [<Reporter: John Smith>] 268 >>> Reporter.objects.filter(article__reporter__exact=r).distinct() 269 [<Reporter: John Smith>] 270 271 # Regression for #12876 -- Model methods that include queries that 272 # recursive don't cause recursion depth problems under deepcopy. 273 >>> r.cached_query = Article.objects.filter(reporter=r) 274 >>> from copy import deepcopy 275 >>> deepcopy(r) 276 <Reporter: John Smith> 277 278 # Check that implied __exact also works. 279 >>> Reporter.objects.filter(article__reporter=r).distinct() 280 [<Reporter: John Smith>] 281 282 # It's possible to use values() calls across many-to-one relations. (Note, 283 # too, that we clear the ordering here so as not to drag the 'headline' 284 # field into the columns being used to determine uniqueness.) 285 >>> d = {'reporter__first_name': u'John', 'reporter__last_name': u'Smith'} 286 >>> list(Article.objects.filter(reporter=r).distinct().order_by().values('reporter__first_name', 'reporter__last_name')) == [d] 287 True 288 289 # If you delete a reporter, his articles will be deleted. 290 >>> Article.objects.all() 291 [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>, <Article: This is a test>, <Article: This is a test>] 292 >>> Reporter.objects.order_by('first_name') 293 [<Reporter: John Smith>, <Reporter: Paul Jones>] 294 >>> r2.delete() 295 >>> Article.objects.all() 296 [<Article: John's second story>, <Article: This is a test>, <Article: This is a test>, <Article: This is a test>] 297 >>> Reporter.objects.order_by('first_name') 298 [<Reporter: John Smith>] 299 300 # You can delete using a JOIN in the query. 301 >>> Reporter.objects.filter(article__headline__startswith='This').delete() 302 >>> Reporter.objects.all() 303 [] 304 >>> Article.objects.all() 305 [] 306 307 # Check that Article.objects.select_related().dates() works properly when 308 # there are multiple Articles with the same date but different foreign-key 309 # objects (Reporters). 310 >>> r1 = Reporter.objects.create(first_name='Mike', last_name='Royko', email='royko@suntimes.com') 311 >>> r2 = Reporter.objects.create(first_name='John', last_name='Kass', email='jkass@tribune.com') 312 >>> a1 = Article.objects.create(headline='First', pub_date=datetime(1980, 4, 23), reporter=r1) 313 >>> a2 = Article.objects.create(headline='Second', pub_date=datetime(1980, 4, 23), reporter=r2) 314 >>> Article.objects.select_related().dates('pub_date', 'day') 315 [datetime.datetime(1980, 4, 23, 0, 0)] 316 >>> Article.objects.select_related().dates('pub_date', 'month') 317 [datetime.datetime(1980, 4, 1, 0, 0)] 318 >>> Article.objects.select_related().dates('pub_date', 'year') 319 [datetime.datetime(1980, 1, 1, 0, 0)] -
new file docs/topics/db/examples/one_to_one.txt
diff --git a/docs/topics/db/examples/one_to_one.txt b/docs/topics/db/examples/one_to_one.txt new file mode 100644
- + 1 ############################ 2 10. One-to-one relationships 3 ############################ 4 5 To define a one-to-one relationship, use ``OneToOneField()``. 6 7 In this example, a ``Place`` optionally can be a ``Restaurant``:: 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 What follows are examples of operations that can be performed using the Python 50 API facilities:: 51 52 :: 53 54 >>> # Create a couple of Places. 55 >>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton') 56 >>> p1.save() 57 >>> p2 = Place(name='Ace Hardware', address='1013 N. Ashland') 58 >>> p2.save() 59 60 # Create a Restaurant. Pass the ID of the "parent" object as this object's ID. 61 >>> r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False) 62 >>> r.save() 63 64 # A Restaurant can access its place. 65 >>> r.place 66 <Place: Demon Dogs the place> 67 68 # A Place can access its restaurant, if available. 69 >>> p1.restaurant 70 <Restaurant: Demon Dogs the restaurant> 71 72 # p2 doesn't have an associated restaurant. 73 >>> p2.restaurant 74 Traceback (most recent call last): 75 ... 76 DoesNotExist: Restaurant matching query does not exist. 77 78 # Set the place using assignment notation. Because place is the primary key on 79 # Restaurant, the save will create a new restaurant 80 >>> r.place = p2 81 >>> r.save() 82 >>> p2.restaurant 83 <Restaurant: Ace Hardware the restaurant> 84 >>> r.place 85 <Place: Ace Hardware the place> 86 >>> p2.id 87 2 88 89 # Set the place back again, using assignment in the reverse direction. 90 >>> p1.restaurant = r 91 >>> p1.restaurant 92 <Restaurant: Demon Dogs the restaurant> 93 94 >>> r = Restaurant.objects.get(pk=1) 95 >>> r.place 96 <Place: Demon Dogs the place> 97 98 # Restaurant.objects.all() just returns the Restaurants, not the Places. 99 # Note that there are two restaurants - Ace Hardware the Restaurant was created 100 # in the call to r.place = p2. 101 >>> Restaurant.objects.all() 102 [<Restaurant: Demon Dogs the restaurant>, <Restaurant: Ace Hardware the restaurant>] 103 104 # Place.objects.all() returns all Places, regardless of whether they have 105 # Restaurants. 106 >>> Place.objects.order_by('name') 107 [<Place: Ace Hardware the place>, <Place: Demon Dogs the place>] 108 109 >>> Restaurant.objects.get(place__id__exact=1) 110 <Restaurant: Demon Dogs the restaurant> 111 >>> Restaurant.objects.get(pk=1) 112 <Restaurant: Demon Dogs the restaurant> 113 >>> Restaurant.objects.get(place__exact=1) 114 <Restaurant: Demon Dogs the restaurant> 115 >>> Restaurant.objects.get(place__exact=p1) 116 <Restaurant: Demon Dogs the restaurant> 117 >>> Restaurant.objects.get(place=1) 118 <Restaurant: Demon Dogs the restaurant> 119 >>> Restaurant.objects.get(place=p1) 120 <Restaurant: Demon Dogs the restaurant> 121 >>> Restaurant.objects.get(place__pk=1) 122 <Restaurant: Demon Dogs the restaurant> 123 >>> Restaurant.objects.get(place__name__startswith="Demon") 124 <Restaurant: Demon Dogs the restaurant> 125 126 >>> Place.objects.get(id__exact=1) 127 <Place: Demon Dogs the place> 128 >>> Place.objects.get(pk=1) 129 <Place: Demon Dogs the place> 130 >>> Place.objects.get(restaurant__place__exact=1) 131 <Place: Demon Dogs the place> 132 >>> Place.objects.get(restaurant__place__exact=p1) 133 <Place: Demon Dogs the place> 134 >>> Place.objects.get(restaurant__pk=1) 135 <Place: Demon Dogs the place> 136 >>> Place.objects.get(restaurant=1) 137 <Place: Demon Dogs the place> 138 >>> Place.objects.get(restaurant=r) 139 <Place: Demon Dogs the place> 140 >>> Place.objects.get(restaurant__exact=1) 141 <Place: Demon Dogs the place> 142 >>> Place.objects.get(restaurant__exact=r) 143 <Place: Demon Dogs the place> 144 145 # Add a Waiter to the Restaurant. 146 >>> w = r.waiter_set.create(name='Joe') 147 >>> w.save() 148 >>> w 149 <Waiter: Joe the waiter at Demon Dogs the restaurant> 150 151 # Query the waiters 152 >>> Waiter.objects.filter(restaurant__place__pk=1) 153 [<Waiter: Joe the waiter at Demon Dogs the restaurant>] 154 >>> Waiter.objects.filter(restaurant__place__exact=1) 155 [<Waiter: Joe the waiter at Demon Dogs the restaurant>] 156 >>> Waiter.objects.filter(restaurant__place__exact=p1) 157 [<Waiter: Joe the waiter at Demon Dogs the restaurant>] 158 >>> Waiter.objects.filter(restaurant__pk=1) 159 [<Waiter: Joe the waiter at Demon Dogs the restaurant>] 160 >>> Waiter.objects.filter(id__exact=1) 161 [<Waiter: Joe the waiter at Demon Dogs the restaurant>] 162 >>> Waiter.objects.filter(pk=1) 163 [<Waiter: Joe the waiter at Demon Dogs the restaurant>] 164 >>> Waiter.objects.filter(restaurant=1) 165 [<Waiter: Joe the waiter at Demon Dogs the restaurant>] 166 >>> Waiter.objects.filter(restaurant=r) 167 [<Waiter: Joe the waiter at Demon Dogs the restaurant>] 168 169 # Delete the restaurant; the waiter should also be removed 170 >>> r = Restaurant.objects.get(pk=1) 171 >>> r.delete() 172 173 # One-to-one fields still work if you create your own primary key 174 >>> o1 = ManualPrimaryKey(primary_key="abc123", name="primary") 175 >>> o1.save() 176 >>> o2 = RelatedModel(link=o1, name="secondary") 177 >>> o2.save() 178 179 # You can have multiple one-to-one fields on a model, too. 180 >>> x1 = MultiModel(link1=p1, link2=o1, name="x1") 181 >>> x1.save() 182 >>> o1.multimodel 183 <MultiModel: Multimodel x1> 184 185 # This will fail because each one-to-one field must be unique (and link2=o1 was 186 # used for x1, above). 187 >>> sid = transaction.savepoint() 188 >>> try: 189 ... MultiModel(link1=p2, link2=o1, name="x1").save() 190 ... except Exception, e: 191 ... if isinstance(e, IntegrityError): 192 ... print "Pass" 193 ... else: 194 ... print "Fail with %s" % type(e) 195 Pass 196 >>> transaction.savepoint_rollback(sid) -
docs/topics/db/models.txt
diff --git a/docs/topics/db/models.txt b/docs/topics/db/models.txt
a b 18 18 * With all of this, Django gives you an automatically-generated 19 19 database-access API; see :doc:`/topics/db/queries`. 20 20 21 .. seealso::22 23 A companion to this document is the `official repository of model24 examples`_. (In the Django source distribution, these examples are in the25 ``tests/modeltests`` directory.)26 27 .. _official repository of model examples: http://code.djangoproject.com/browser/django/trunk/tests/modeltests28 29 21 Quick example 30 22 ============= 31 23 … … 326 318 For details on accessing backwards-related objects, see the 327 319 :ref:`Following relationships backward example <backwards-related-objects>`. 328 320 329 For sample code, see the `Many-to-one relationship model tests`_. 330 331 .. _Many-to-one relationship model tests: http://code.djangoproject.com/browser/django/trunk/tests/modeltests/many_to_one 321 For sample code, see the :doc:`Many-to-one relationship model tests 322 </topics/db/examples/many_to_one>`. 332 323 333 324 Many-to-many relationships 334 325 ~~~~~~~~~~~~~~~~~~~~~~~~~~ … … 376 367 377 368 .. seealso:: 378 369 379 See the `Many-to-many relationship model example`_ for a full example. 380 381 .. _Many-to-many relationship model example: http://code.djangoproject.com/browser/django/trunk/tests/modeltests/many_to_many/models.py 370 See the :doc:`Many-to-many relationship model example 371 </topics/db/examples/many_to_many>` for a full example. 382 372 383 373 :class:`~django.db.models.ManyToManyField` fields also accept a number of extra 384 374 arguments which are explained in :ref:`the model field reference … … 569 559 570 560 .. seealso:: 571 561 572 See the `One-to-one relationship model example`_ for a full example. 573 574 .. _One-to-one relationship model example: http://code.djangoproject.com/browser/django/trunk/tests/modeltests/one_to_one/models.py 562 See the :doc:`One-to-one relationship model example 563 </topics/db/examples/one_to_one>` for a full example. 575 564 576 565 :class:`~django.db.models.OneToOneField` fields also accept one optional argument 577 566 described in the :ref:`model field reference <ref-onetoone>`.