Fixed #17605: Restored deleted query documentation that used to live in doctests. Thanks zsiciarz for work on the patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17737 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
1235cd376e
commit
dad1f5c21e
|
@ -0,0 +1,10 @@
|
|||
========================================
|
||||
Examples of model relationship API usage
|
||||
========================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
many_to_many
|
||||
many_to_one
|
||||
one_to_one
|
|
@ -0,0 +1,289 @@
|
|||
##########################
|
||||
Many-to-many relationships
|
||||
##########################
|
||||
|
||||
.. highlight:: pycon
|
||||
|
||||
To define a many-to-many relationship, use :ref:`ref-manytomany`.
|
||||
|
||||
In this example, an ``Article`` can be published in multiple ``Publication``
|
||||
objects, and a ``Publication`` has multiple ``Article`` objects:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.db import models
|
||||
|
||||
class Publication(models.Model):
|
||||
title = models.CharField(max_length=30)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
class Meta:
|
||||
ordering = ('title',)
|
||||
|
||||
class Article(models.Model):
|
||||
headline = models.CharField(max_length=100)
|
||||
publications = models.ManyToManyField(Publication)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.headline
|
||||
|
||||
class Meta:
|
||||
ordering = ('headline',)
|
||||
|
||||
What follows are examples of operations that can be performed using the Python
|
||||
API facilities.
|
||||
|
||||
Create a couple of Publications::
|
||||
|
||||
>>> p1 = Publication(title='The Python Journal')
|
||||
>>> p1.save()
|
||||
>>> p2 = Publication(title='Science News')
|
||||
>>> p2.save()
|
||||
>>> p3 = Publication(title='Science Weekly')
|
||||
>>> p3.save()
|
||||
|
||||
Create an Article::
|
||||
|
||||
>>> a1 = Article(headline='Django lets you build Web apps easily')
|
||||
|
||||
You can't associate it with a Publication until it's been saved::
|
||||
|
||||
>>> a1.publications.add(p1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: 'Article' instance needs to have a primary key value before a many-to-many relationship can be used.
|
||||
|
||||
Save it!
|
||||
::
|
||||
|
||||
>>> a1.save()
|
||||
|
||||
Associate the Article with a Publication::
|
||||
|
||||
>>> a1.publications.add(p1)
|
||||
|
||||
Create another Article, and set it to appear in both Publications::
|
||||
|
||||
>>> a2 = Article(headline='NASA uses Python')
|
||||
>>> a2.save()
|
||||
>>> a2.publications.add(p1, p2)
|
||||
>>> a2.publications.add(p3)
|
||||
|
||||
Adding a second time is OK::
|
||||
|
||||
>>> a2.publications.add(p3)
|
||||
|
||||
Adding an object of the wrong type raises TypeError::
|
||||
|
||||
>>> a2.publications.add(a1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: 'Publication' instance expected
|
||||
|
||||
Add a Publication directly via publications.add by using keyword arguments::
|
||||
|
||||
>>> new_publication = a2.publications.create(title='Highlights for Children')
|
||||
|
||||
Article objects have access to their related Publication objects::
|
||||
|
||||
>>> a1.publications.all()
|
||||
[<Publication: The Python Journal>]
|
||||
>>> a2.publications.all()
|
||||
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
|
||||
|
||||
Publication objects have access to their related Article objects::
|
||||
|
||||
>>> p2.article_set.all()
|
||||
[<Article: NASA uses Python>]
|
||||
>>> p1.article_set.all()
|
||||
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
|
||||
>>> Publication.objects.get(id=4).article_set.all()
|
||||
[<Article: NASA uses Python>]
|
||||
|
||||
Many-to-many relationships can be queried using :ref:`lookups across relationships <lookups-that-span-relationships>`::
|
||||
|
||||
>>> Article.objects.filter(publications__id__exact=1)
|
||||
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
|
||||
>>> Article.objects.filter(publications__pk=1)
|
||||
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
|
||||
>>> Article.objects.filter(publications=1)
|
||||
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
|
||||
>>> Article.objects.filter(publications=p1)
|
||||
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
|
||||
|
||||
>>> Article.objects.filter(publications__title__startswith="Science")
|
||||
[<Article: NASA uses Python>, <Article: NASA uses Python>]
|
||||
|
||||
>>> Article.objects.filter(publications__title__startswith="Science").distinct()
|
||||
[<Article: NASA uses Python>]
|
||||
|
||||
The count() function respects distinct() as well::
|
||||
|
||||
>>> Article.objects.filter(publications__title__startswith="Science").count()
|
||||
2
|
||||
|
||||
>>> Article.objects.filter(publications__title__startswith="Science").distinct().count()
|
||||
1
|
||||
|
||||
>>> Article.objects.filter(publications__in=[1,2]).distinct()
|
||||
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
|
||||
>>> Article.objects.filter(publications__in=[p1,p2]).distinct()
|
||||
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
|
||||
|
||||
Reverse m2m queries are supported (i.e., starting at the table that doesn't have
|
||||
a ManyToManyField)::
|
||||
|
||||
>>> Publication.objects.filter(id__exact=1)
|
||||
[<Publication: The Python Journal>]
|
||||
>>> Publication.objects.filter(pk=1)
|
||||
[<Publication: The Python Journal>]
|
||||
|
||||
>>> Publication.objects.filter(article__headline__startswith="NASA")
|
||||
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
|
||||
|
||||
>>> Publication.objects.filter(article__id__exact=1)
|
||||
[<Publication: The Python Journal>]
|
||||
>>> Publication.objects.filter(article__pk=1)
|
||||
[<Publication: The Python Journal>]
|
||||
>>> Publication.objects.filter(article=1)
|
||||
[<Publication: The Python Journal>]
|
||||
>>> Publication.objects.filter(article=a1)
|
||||
[<Publication: The Python Journal>]
|
||||
|
||||
>>> Publication.objects.filter(article__in=[1,2]).distinct()
|
||||
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
|
||||
>>> Publication.objects.filter(article__in=[a1,a2]).distinct()
|
||||
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
|
||||
|
||||
Excluding a related item works as you would expect, too (although the SQL
|
||||
involved is a little complex)::
|
||||
|
||||
>>> Article.objects.exclude(publications=p2)
|
||||
[<Article: Django lets you build Web apps easily>]
|
||||
|
||||
If we delete a Publication, its Articles won't be able to access it::
|
||||
|
||||
>>> p1.delete()
|
||||
>>> Publication.objects.all()
|
||||
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>]
|
||||
>>> a1 = Article.objects.get(pk=1)
|
||||
>>> a1.publications.all()
|
||||
[]
|
||||
|
||||
If we delete an Article, its Publications won't be able to access it::
|
||||
|
||||
>>> a2.delete()
|
||||
>>> Article.objects.all()
|
||||
[<Article: Django lets you build Web apps easily>]
|
||||
>>> p2.article_set.all()
|
||||
[]
|
||||
|
||||
Adding via the 'other' end of an m2m::
|
||||
|
||||
>>> a4 = Article(headline='NASA finds intelligent life on Earth')
|
||||
>>> a4.save()
|
||||
>>> p2.article_set.add(a4)
|
||||
>>> p2.article_set.all()
|
||||
[<Article: NASA finds intelligent life on Earth>]
|
||||
>>> a4.publications.all()
|
||||
[<Publication: Science News>]
|
||||
|
||||
Adding via the other end using keywords::
|
||||
|
||||
>>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders')
|
||||
>>> p2.article_set.all()
|
||||
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
|
||||
>>> a5 = p2.article_set.all()[1]
|
||||
>>> a5.publications.all()
|
||||
[<Publication: Science News>]
|
||||
|
||||
Removing publication from an article::
|
||||
|
||||
>>> a4.publications.remove(p2)
|
||||
>>> p2.article_set.all()
|
||||
[<Article: Oxygen-free diet works wonders>]
|
||||
>>> a4.publications.all()
|
||||
[]
|
||||
|
||||
And from the other end::
|
||||
|
||||
>>> p2.article_set.remove(a5)
|
||||
>>> p2.article_set.all()
|
||||
[]
|
||||
>>> a5.publications.all()
|
||||
[]
|
||||
|
||||
Relation sets can be assigned. Assignment clears any existing set members::
|
||||
|
||||
>>> a4.publications.all()
|
||||
[<Publication: Science News>]
|
||||
>>> a4.publications = [p3]
|
||||
>>> a4.publications.all()
|
||||
[<Publication: Science Weekly>]
|
||||
|
||||
Relation sets can be cleared::
|
||||
|
||||
>>> p2.article_set.clear()
|
||||
>>> p2.article_set.all()
|
||||
[]
|
||||
|
||||
And you can clear from the other end::
|
||||
|
||||
>>> p2.article_set.add(a4, a5)
|
||||
>>> p2.article_set.all()
|
||||
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
|
||||
>>> a4.publications.all()
|
||||
[<Publication: Science News>, <Publication: Science Weekly>]
|
||||
>>> a4.publications.clear()
|
||||
>>> a4.publications.all()
|
||||
[]
|
||||
>>> p2.article_set.all()
|
||||
[<Article: Oxygen-free diet works wonders>]
|
||||
|
||||
Recreate the article and Publication we have deleted::
|
||||
|
||||
>>> p1 = Publication(title='The Python Journal')
|
||||
>>> p1.save()
|
||||
>>> a2 = Article(headline='NASA uses Python')
|
||||
>>> a2.save()
|
||||
>>> a2.publications.add(p1, p2, p3)
|
||||
|
||||
Bulk delete some Publications - references to deleted publications should go::
|
||||
|
||||
>>> Publication.objects.filter(title__startswith='Science').delete()
|
||||
>>> Publication.objects.all()
|
||||
[<Publication: Highlights for Children>, <Publication: The Python Journal>]
|
||||
>>> Article.objects.all()
|
||||
[<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>]
|
||||
>>> a2.publications.all()
|
||||
[<Publication: The Python Journal>]
|
||||
|
||||
Bulk delete some articles - references to deleted objects should go::
|
||||
|
||||
>>> q = Article.objects.filter(headline__startswith='Django')
|
||||
>>> print q
|
||||
[<Article: Django lets you build Web apps easily>]
|
||||
>>> q.delete()
|
||||
|
||||
After the delete, the QuerySet cache needs to be cleared, and the referenced
|
||||
objects should be gone::
|
||||
|
||||
>>> print q
|
||||
[]
|
||||
>>> p1.article_set.all()
|
||||
[<Article: NASA uses Python>]
|
||||
|
||||
An alternate to calling clear() is to assign the empty set::
|
||||
|
||||
>>> p1.article_set = []
|
||||
>>> p1.article_set.all()
|
||||
[]
|
||||
|
||||
>>> a2.publications = [p1, new_publication]
|
||||
>>> a2.publications.all()
|
||||
[<Publication: Highlights for Children>, <Publication: The Python Journal>]
|
||||
>>> a2.publications = []
|
||||
>>> a2.publications.all()
|
||||
[]
|
|
@ -0,0 +1,208 @@
|
|||
#########################
|
||||
Many-to-one relationships
|
||||
#########################
|
||||
|
||||
.. highlight:: pycon
|
||||
|
||||
To define a many-to-one relationship, use :class:`~django.db.models.ForeignKey`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.db import models
|
||||
|
||||
class Reporter(models.Model):
|
||||
first_name = models.CharField(max_length=30)
|
||||
last_name = models.CharField(max_length=30)
|
||||
email = models.EmailField()
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s %s" % (self.first_name, self.last_name)
|
||||
|
||||
class Article(models.Model):
|
||||
headline = models.CharField(max_length=100)
|
||||
pub_date = models.DateField()
|
||||
reporter = models.ForeignKey(Reporter)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.headline
|
||||
|
||||
class Meta:
|
||||
ordering = ('headline',)
|
||||
|
||||
What follows are examples of operations that can be performed using the Python
|
||||
API facilities.
|
||||
|
||||
Create a few Reporters::
|
||||
|
||||
>>> r = Reporter(first_name='John', last_name='Smith', email='john@example.com')
|
||||
>>> r.save()
|
||||
|
||||
>>> r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
|
||||
>>> r2.save()
|
||||
|
||||
Create an Article::
|
||||
|
||||
>>> from datetime import datetime
|
||||
>>> a = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter=r)
|
||||
>>> a.save()
|
||||
|
||||
>>> a.reporter.id
|
||||
1
|
||||
|
||||
>>> a.reporter
|
||||
<Reporter: John Smith>
|
||||
|
||||
Article objects have access to their related Reporter objects::
|
||||
|
||||
>>> r = a.reporter
|
||||
|
||||
These are strings instead of unicode strings because that's what was used in
|
||||
the creation of this reporter (and we haven't refreshed the data from the
|
||||
database, which always returns unicode strings)::
|
||||
|
||||
>>> r.first_name, r.last_name
|
||||
('John', 'Smith')
|
||||
|
||||
Create an Article via the Reporter object::
|
||||
|
||||
>>> new_article = r.article_set.create(headline="John's second story", pub_date=datetime(2005, 7, 29))
|
||||
>>> new_article
|
||||
<Article: John's second story>
|
||||
>>> new_article.reporter
|
||||
<Reporter: John Smith>
|
||||
>>> new_article.reporter.id
|
||||
1
|
||||
|
||||
Create a new article, and add it to the article set::
|
||||
|
||||
>>> new_article2 = Article(headline="Paul's story", pub_date=datetime(2006, 1, 17))
|
||||
>>> r.article_set.add(new_article2)
|
||||
>>> new_article2.reporter
|
||||
<Reporter: John Smith>
|
||||
>>> new_article2.reporter.id
|
||||
1
|
||||
>>> r.article_set.all()
|
||||
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
|
||||
|
||||
Add the same article to a different article set - check that it moves::
|
||||
|
||||
>>> r2.article_set.add(new_article2)
|
||||
>>> new_article2.reporter.id
|
||||
2
|
||||
>>> new_article2.reporter
|
||||
<Reporter: Paul Jones>
|
||||
|
||||
Adding an object of the wrong type raises TypeError::
|
||||
|
||||
>>> r.article_set.add(r2)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: 'Article' instance expected
|
||||
|
||||
>>> r.article_set.all()
|
||||
[<Article: John's second story>, <Article: This is a test>]
|
||||
>>> r2.article_set.all()
|
||||
[<Article: Paul's story>]
|
||||
|
||||
>>> r.article_set.count()
|
||||
2
|
||||
|
||||
>>> r2.article_set.count()
|
||||
1
|
||||
|
||||
Note that in the last example the article has moved from John to Paul.
|
||||
|
||||
Related managers support field lookups as well.
|
||||
The API automatically follows relationships as far as you need.
|
||||
Use double underscores to separate relationships.
|
||||
This works as many levels deep as you want. There's no limit. For example::
|
||||
|
||||
>>> r.article_set.filter(headline__startswith='This')
|
||||
[<Article: This is a test>]
|
||||
|
||||
# Find all Articles for any Reporter whose first name is "John".
|
||||
>>> Article.objects.filter(reporter__first_name__exact='John')
|
||||
[<Article: John's second story>, <Article: This is a test>]
|
||||
|
||||
Exact match is implied here::
|
||||
|
||||
>>> Article.objects.filter(reporter__first_name='John')
|
||||
[<Article: John's second story>, <Article: This is a test>]
|
||||
|
||||
Query twice over the related field. This translates to an AND condition in the
|
||||
WHERE clause::
|
||||
|
||||
>>> Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith')
|
||||
[<Article: John's second story>, <Article: This is a test>]
|
||||
|
||||
For the related lookup you can supply a primary key value or pass the related
|
||||
object explicitly::
|
||||
|
||||
>>> Article.objects.filter(reporter__pk=1)
|
||||
[<Article: John's second story>, <Article: This is a test>]
|
||||
>>> Article.objects.filter(reporter=1)
|
||||
[<Article: John's second story>, <Article: This is a test>]
|
||||
>>> Article.objects.filter(reporter=r)
|
||||
[<Article: John's second story>, <Article: This is a test>]
|
||||
|
||||
>>> Article.objects.filter(reporter__in=[1,2]).distinct()
|
||||
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
|
||||
>>> Article.objects.filter(reporter__in=[r,r2]).distinct()
|
||||
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
|
||||
|
||||
You can also use a queryset instead of a literal list of instances::
|
||||
|
||||
>>> Article.objects.filter(reporter__in=Reporter.objects.filter(first_name='John')).distinct()
|
||||
[<Article: John's second story>, <Article: This is a test>]
|
||||
|
||||
Querying in the opposite direction::
|
||||
|
||||
>>> Reporter.objects.filter(article__pk=1)
|
||||
[<Reporter: John Smith>]
|
||||
>>> Reporter.objects.filter(article=1)
|
||||
[<Reporter: John Smith>]
|
||||
>>> Reporter.objects.filter(article=a)
|
||||
[<Reporter: John Smith>]
|
||||
|
||||
>>> Reporter.objects.filter(article__headline__startswith='This')
|
||||
[<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]
|
||||
>>> Reporter.objects.filter(article__headline__startswith='This').distinct()
|
||||
[<Reporter: John Smith>]
|
||||
|
||||
Counting in the opposite direction works in conjunction with distinct()::
|
||||
|
||||
>>> Reporter.objects.filter(article__headline__startswith='This').count()
|
||||
3
|
||||
>>> Reporter.objects.filter(article__headline__startswith='This').distinct().count()
|
||||
1
|
||||
|
||||
Queries can go round in circles::
|
||||
|
||||
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John')
|
||||
[<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]
|
||||
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct()
|
||||
[<Reporter: John Smith>]
|
||||
>>> Reporter.objects.filter(article__reporter__exact=r).distinct()
|
||||
[<Reporter: John Smith>]
|
||||
|
||||
If you delete a reporter, his articles will be deleted (assuming that the
|
||||
ForeignKey was defined with :attr:`django.db.models.ForeignKey.on_delete` set to
|
||||
``CASCADE``, which is the default)::
|
||||
|
||||
>>> Article.objects.all()
|
||||
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
|
||||
>>> Reporter.objects.order_by('first_name')
|
||||
[<Reporter: John Smith>, <Reporter: Paul Jones>]
|
||||
>>> r2.delete()
|
||||
>>> Article.objects.all()
|
||||
[<Article: John's second story>, <Article: This is a test>]
|
||||
>>> Reporter.objects.order_by('first_name')
|
||||
[<Reporter: John Smith>]
|
||||
|
||||
You can delete using a JOIN in the query::
|
||||
|
||||
>>> Reporter.objects.filter(article__headline__startswith='This').delete()
|
||||
>>> Reporter.objects.all()
|
||||
[]
|
||||
>>> Article.objects.all()
|
||||
[]
|
|
@ -0,0 +1,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>]
|
|
@ -19,3 +19,4 @@ model maps to a single database table.
|
|||
multi-db
|
||||
tablespaces
|
||||
optimization
|
||||
examples/index
|
||||
|
|
|
@ -18,13 +18,6 @@ The basics:
|
|||
* With all of this, Django gives you an automatically-generated
|
||||
database-access API; see :doc:`/topics/db/queries`.
|
||||
|
||||
.. seealso::
|
||||
|
||||
A companion to this document is the `official repository of model
|
||||
examples`_. (In the Django source distribution, these examples are in the
|
||||
``tests/modeltests`` directory.)
|
||||
|
||||
.. _official repository of model examples: https://code.djangoproject.com/browser/django/trunk/tests/modeltests
|
||||
|
||||
Quick example
|
||||
=============
|
||||
|
@ -326,9 +319,6 @@ whatever you want. For example::
|
|||
For details on accessing backwards-related objects, see the
|
||||
:ref:`Following relationships backward example <backwards-related-objects>`.
|
||||
|
||||
For sample code, see the `Many-to-one relationship model tests`_.
|
||||
|
||||
.. _Many-to-one relationship model tests: https://code.djangoproject.com/browser/django/trunk/tests/modeltests/many_to_one
|
||||
|
||||
Many-to-many relationships
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -376,10 +366,6 @@ form would let users select the toppings.
|
|||
|
||||
.. seealso::
|
||||
|
||||
See the `Many-to-many relationship model example`_ for a full example.
|
||||
|
||||
.. _Many-to-many relationship model example: https://code.djangoproject.com/browser/django/trunk/tests/modeltests/many_to_many/models.py
|
||||
|
||||
:class:`~django.db.models.ManyToManyField` fields also accept a number of extra
|
||||
arguments which are explained in :ref:`the model field reference
|
||||
<manytomany-arguments>`. These options help define how the relationship should
|
||||
|
@ -569,10 +555,6 @@ can be made; see :ref:`the model field reference <ref-onetoone>` for details.
|
|||
|
||||
.. seealso::
|
||||
|
||||
See the `One-to-one relationship model example`_ for a full example.
|
||||
|
||||
.. _One-to-one relationship model example: https://code.djangoproject.com/browser/django/trunk/tests/modeltests/one_to_one/models.py
|
||||
|
||||
:class:`~django.db.models.OneToOneField` fields also accept one optional argument
|
||||
described in the :ref:`model field reference <ref-onetoone>`.
|
||||
|
||||
|
|
|
@ -483,6 +483,8 @@ probably use:
|
|||
Again, this only scratches the surface. A complete reference can be found in the
|
||||
:ref:`field lookup reference <field-lookups>`.
|
||||
|
||||
.. _lookups-that-span-relationships:
|
||||
|
||||
Lookups that span relationships
|
||||
-------------------------------
|
||||
|
||||
|
|
Loading…
Reference in New Issue