Ticket #17605: 17605-2.diff

File 17605-2.diff, 33.7 KB (added by Ramiro Morales, 12 years ago)

Alternative patch adding a topics/db/examples/ hierarchy

  • 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##########################
     2Many-to-many relationships
     3##########################
     4
     5To define a many-to-many relationship, use ``ManyToManyField()``.
     6
     7In this example, an ``Article`` can be published in multiple ``Publication``
     8objects, 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
     31What follows are examples of operations that can be performed using the Python
     32API 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#########################
     2Many-to-one relationships
     3#########################
     4
     5To 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
     30What follows are examples of operations that can be performed using the Python
     31API 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############################
     210. One-to-one relationships
     3############################
     4
     5To define a one-to-one relationship, use ``OneToOneField()``.
     6
     7In 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
     49What follows are examples of operations that can be performed using the Python
     50API 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  
    1818* With all of this, Django gives you an automatically-generated
    1919  database-access API; see :doc:`/topics/db/queries`.
    2020
    21 .. seealso::
    22 
    23     A companion to this document is the `official repository of model
    24     examples`_. (In the Django source distribution, these examples are in the
    25     ``tests/modeltests`` directory.)
    26 
    27     .. _official repository of model examples: http://code.djangoproject.com/browser/django/trunk/tests/modeltests
    28 
    2921Quick example
    3022=============
    3123
     
    326318    For details on accessing backwards-related objects, see the
    327319    :ref:`Following relationships backward example <backwards-related-objects>`.
    328320
    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>`.
    332323
    333324Many-to-many relationships
    334325~~~~~~~~~~~~~~~~~~~~~~~~~~
     
    376367
    377368.. seealso::
    378369
    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.
    382372
    383373:class:`~django.db.models.ManyToManyField` fields also accept a number of extra
    384374arguments which are explained in :ref:`the model field reference
     
    569559
    570560.. seealso::
    571561
    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.
    575564
    576565:class:`~django.db.models.OneToOneField` fields also accept one optional argument
    577566described in the :ref:`model field reference <ref-onetoone>`.
Back to Top