Fixed #25508 -- Modified QuerySet.__repr__() to disambiguate it from a list.

This commit is contained in:
Tim Graham 2015-10-05 19:07:34 -04:00
parent 3543fec3b7
commit e0837f2cb1
20 changed files with 185 additions and 184 deletions

View File

@ -234,7 +234,7 @@ class QuerySet(object):
data = list(self[:REPR_OUTPUT_SIZE + 1]) data = list(self[:REPR_OUTPUT_SIZE + 1])
if len(data) > REPR_OUTPUT_SIZE: if len(data) > REPR_OUTPUT_SIZE:
data[-1] = "...(remaining elements truncated)..." data[-1] = "...(remaining elements truncated)..."
return repr(data) return '<QuerySet %r>' % data
def __len__(self): def __len__(self):
self._fetch_all() self._fetch_all()

View File

@ -73,7 +73,7 @@ necessary:
# No reporters are in the system yet. # No reporters are in the system yet.
>>> Reporter.objects.all() >>> Reporter.objects.all()
[] <QuerySet []>
# Create a new Reporter. # Create a new Reporter.
>>> r = Reporter(full_name='John Smith') >>> r = Reporter(full_name='John Smith')
@ -87,7 +87,7 @@ necessary:
# Now the new reporter is in the database. # Now the new reporter is in the database.
>>> Reporter.objects.all() >>> Reporter.objects.all()
[<Reporter: John Smith>] <QuerySet [<Reporter: John Smith>]>
# Fields are represented as attributes on the Python object. # Fields are represented as attributes on the Python object.
>>> r.full_name >>> r.full_name
@ -113,7 +113,7 @@ necessary:
# Now the article is in the database. # Now the article is in the database.
>>> Article.objects.all() >>> Article.objects.all()
[<Article: Django is cool>] <QuerySet [<Article: Django is cool>]>
# Article objects get API access to related Reporter objects. # Article objects get API access to related Reporter objects.
>>> r = a.reporter >>> r = a.reporter
@ -122,13 +122,13 @@ necessary:
# And vice versa: Reporter objects get API access to Article objects. # And vice versa: Reporter objects get API access to Article objects.
>>> r.article_set.all() >>> r.article_set.all()
[<Article: Django is cool>] <QuerySet [<Article: Django is cool>]>
# The API follows relationships as far as you need, performing efficient # The API follows relationships as far as you need, performing efficient
# JOINs for you behind the scenes. # JOINs for you behind the scenes.
# This finds all articles by a reporter whose name starts with "John". # This finds all articles by a reporter whose name starts with "John".
>>> Article.objects.filter(reporter__full_name__startswith='John') >>> Article.objects.filter(reporter__full_name__startswith='John')
[<Article: Django is cool>] <QuerySet [<Article: Django is cool>]>
# Change an object by altering its attributes and calling save(). # Change an object by altering its attributes and calling save().
>>> r.full_name = 'Billy Goat' >>> r.full_name = 'Billy Goat'

View File

@ -401,7 +401,7 @@ Once you're in the shell, explore the :doc:`database API </topics/db/queries>`::
# No questions are in the system yet. # No questions are in the system yet.
>>> Question.objects.all() >>> Question.objects.all()
[] <QuerySet []>
# Create a new Question. # Create a new Question.
# Support for time zones is enabled in the default settings file, so # Support for time zones is enabled in the default settings file, so
@ -432,8 +432,7 @@ Once you're in the shell, explore the :doc:`database API </topics/db/queries>`::
# objects.all() displays all the questions in the database. # objects.all() displays all the questions in the database.
>>> Question.objects.all() >>> Question.objects.all()
[<Question: Question object>] <QuerySet [<Question: Question object>]>
Wait a minute. ``<Question: Question object>`` is, utterly, an unhelpful representation Wait a minute. ``<Question: Question object>`` is, utterly, an unhelpful representation
of this object. Let's fix that by editing the ``Question`` model (in the of this object. Let's fix that by editing the ``Question`` model (in the
@ -494,14 +493,14 @@ Save these changes and start a new Python interactive shell by running
# Make sure our __str__() addition worked. # Make sure our __str__() addition worked.
>>> Question.objects.all() >>> Question.objects.all()
[<Question: What's up?>] <QuerySet [<Question: What's up?>]>
# Django provides a rich database lookup API that's entirely driven by # Django provides a rich database lookup API that's entirely driven by
# keyword arguments. # keyword arguments.
>>> Question.objects.filter(id=1) >>> Question.objects.filter(id=1)
[<Question: What's up?>] <QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What') >>> Question.objects.filter(question_text__startswith='What')
[<Question: What's up?>] <QuerySet [<Question: What's up?>]>
# Get the question that was published this year. # Get the question that was published this year.
>>> from django.utils import timezone >>> from django.utils import timezone
@ -535,7 +534,7 @@ Save these changes and start a new Python interactive shell by running
# Display any choices from the related object set -- none so far. # Display any choices from the related object set -- none so far.
>>> q.choice_set.all() >>> q.choice_set.all()
[] <QuerySet []>
# Create three choices. # Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0) >>> q.choice_set.create(choice_text='Not much', votes=0)
@ -550,7 +549,7 @@ Save these changes and start a new Python interactive shell by running
# And vice versa: Question objects get access to Choice objects. # And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all() >>> q.choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count() >>> q.choice_set.count()
3 3
@ -560,7 +559,7 @@ Save these changes and start a new Python interactive shell by running
# Find all Choices for any question whose pub_date is in this year # Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above). # (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year) >>> Choice.objects.filter(question__pub_date__year=current_year)
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
# Let's delete one of the choices. Use delete() for that. # Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking') >>> c = q.choice_set.filter(choice_text__startswith='Just hacking')

View File

@ -383,7 +383,7 @@ With that ready, we can ask the client to do some work for us::
>>> # If the following doesn't work, you probably omitted the call to >>> # If the following doesn't work, you probably omitted the call to
>>> # setup_test_environment() described above >>> # setup_test_environment() described above
>>> response.context['latest_question_list'] >>> response.context['latest_question_list']
[<Question: Who is your favorite Beatle?>] <QuerySet [<Question: Who is your favorite Beatle?>]>
Improving our view Improving our view
------------------ ------------------

View File

@ -382,7 +382,7 @@ be used to retrieve their associated ``TaggedItems``::
>>> t2 = TaggedItem(content_object=b, tag='python') >>> t2 = TaggedItem(content_object=b, tag='python')
>>> t2.save() >>> t2.save()
>>> b.tags.all() >>> b.tags.all()
[<TaggedItem: django>, <TaggedItem: python>] <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
Defining :class:`~django.contrib.contenttypes.fields.GenericRelation` with Defining :class:`~django.contrib.contenttypes.fields.GenericRelation` with
``related_query_name`` set allows querying from the related object:: ``related_query_name`` set allows querying from the related object::
@ -394,7 +394,7 @@ from ``TaggedItem``::
>>> # Get all tags belonging to books containing `django` in the url >>> # Get all tags belonging to books containing `django` in the url
>>> TaggedItem.objects.filter(bookmarks__url__contains='django') >>> TaggedItem.objects.filter(bookmarks__url__contains='django')
[<TaggedItem: django>, <TaggedItem: python>] <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
Just as :class:`~django.contrib.contenttypes.fields.GenericForeignKey` Just as :class:`~django.contrib.contenttypes.fields.GenericForeignKey`
accepts the names of the content-type and object-ID fields as accepts the names of the content-type and object-ID fields as
@ -418,7 +418,7 @@ same types of lookups manually::
>>> bookmark_type = ContentType.objects.get_for_model(b) >>> bookmark_type = ContentType.objects.get_for_model(b)
>>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id, >>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id,
... object_id=b.id) ... object_id=b.id)
[<TaggedItem: django>, <TaggedItem: python>] <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
Note that if the model in a Note that if the model in a
:class:`~django.contrib.contenttypes.fields.GenericRelation` uses a :class:`~django.contrib.contenttypes.fields.GenericRelation` uses a

View File

@ -588,9 +588,8 @@ Consortium (OGC). [#]_ Import the ``WorldBorder`` model, and perform
a ``contains`` lookup using the ``pnt_wkt`` as the parameter:: a ``contains`` lookup using the ``pnt_wkt`` as the parameter::
>>> from world.models import WorldBorder >>> from world.models import WorldBorder
>>> qs = WorldBorder.objects.filter(mpoly__contains=pnt_wkt) >>> WorldBorder.objects.filter(mpoly__contains=pnt_wkt)
>>> qs <QuerySet [<WorldBorder: United States>]>
[<WorldBorder: United States>]
Here, you retrieved a ``QuerySet`` with only one model: the border of the Here, you retrieved a ``QuerySet`` with only one model: the border of the
United States (exactly what you would expect). United States (exactly what you would expect).
@ -602,8 +601,7 @@ of a queryset::
>>> from django.contrib.gis.geos import Point >>> from django.contrib.gis.geos import Point
>>> pnt = Point(12.4604, 43.9420) >>> pnt = Point(12.4604, 43.9420)
>>> sm = WorldBorder.objects.get(mpoly__intersects=pnt) >>> WorldBorder.objects.get(mpoly__intersects=pnt)
>>> sm
<WorldBorder: San Marino> <WorldBorder: San Marino>
The ``contains`` and ``intersects`` lookups are just a subset of the The ``contains`` and ``intersects`` lookups are just a subset of the
@ -638,7 +636,7 @@ of abstraction::
"world_worldborder"."mpoly" FROM "world_worldborder" "world_worldborder"."mpoly" FROM "world_worldborder"
WHERE ST_Intersects("world_worldborder"."mpoly", ST_Transform(%s, 4326)) WHERE ST_Intersects("world_worldborder"."mpoly", ST_Transform(%s, 4326))
>>> qs # printing evaluates the queryset >>> qs # printing evaluates the queryset
[<WorldBorder: United States>] <QuerySet [<WorldBorder: United States>]>
__ http://spatialreference.org/ref/epsg/32140/ __ http://spatialreference.org/ref/epsg/32140/

View File

@ -120,13 +120,13 @@ data. It uses the SQL operator ``@>``. For example::
>>> Post.objects.create(name='Third post', tags=['tutorial', 'django']) >>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])
>>> Post.objects.filter(tags__contains=['thoughts']) >>> Post.objects.filter(tags__contains=['thoughts'])
[<Post: First post>, <Post: Second post>] <QuerySet [<Post: First post>, <Post: Second post>]>
>>> Post.objects.filter(tags__contains=['django']) >>> Post.objects.filter(tags__contains=['django'])
[<Post: First post>, <Post: Third post>] <QuerySet [<Post: First post>, <Post: Third post>]>
>>> Post.objects.filter(tags__contains=['django', 'thoughts']) >>> Post.objects.filter(tags__contains=['django', 'thoughts'])
[<Post: First post>] <QuerySet [<Post: First post>]>
.. fieldlookup:: arrayfield.contained_by .. fieldlookup:: arrayfield.contained_by
@ -142,10 +142,10 @@ passed. It uses the SQL operator ``<@``. For example::
>>> Post.objects.create(name='Third post', tags=['tutorial', 'django']) >>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])
>>> Post.objects.filter(tags__contained_by=['thoughts', 'django']) >>> Post.objects.filter(tags__contained_by=['thoughts', 'django'])
[<Post: First post>, <Post: Second post>] <QuerySet [<Post: First post>, <Post: Second post>]>
>>> Post.objects.filter(tags__contained_by=['thoughts', 'django', 'tutorial']) >>> Post.objects.filter(tags__contained_by=['thoughts', 'django', 'tutorial'])
[<Post: First post>, <Post: Second post>, <Post: Third post>] <QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
.. fieldlookup:: arrayfield.overlap .. fieldlookup:: arrayfield.overlap
@ -160,10 +160,10 @@ the SQL operator ``&&``. For example::
>>> Post.objects.create(name='Third post', tags=['tutorial', 'django']) >>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])
>>> Post.objects.filter(tags__overlap=['thoughts']) >>> Post.objects.filter(tags__overlap=['thoughts'])
[<Post: First post>, <Post: Second post>] <QuerySet [<Post: First post>, <Post: Second post>]>
>>> Post.objects.filter(tags__overlap=['thoughts', 'tutorial']) >>> Post.objects.filter(tags__overlap=['thoughts', 'tutorial'])
[<Post: First post>, <Post: Second post>, <Post: Third post>] <QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
.. fieldlookup:: arrayfield.len .. fieldlookup:: arrayfield.len
@ -177,7 +177,7 @@ available for :class:`~django.db.models.IntegerField`. For example::
>>> Post.objects.create(name='Second post', tags=['thoughts']) >>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.filter(tags__len=1) >>> Post.objects.filter(tags__len=1)
[<Post: Second post>] <QuerySet [<Post: Second post>]>
.. fieldlookup:: arrayfield.index .. fieldlookup:: arrayfield.index
@ -194,13 +194,13 @@ example::
>>> Post.objects.create(name='Second post', tags=['thoughts']) >>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.filter(tags__0='thoughts') >>> Post.objects.filter(tags__0='thoughts')
[<Post: First post>, <Post: Second post>] <QuerySet [<Post: First post>, <Post: Second post>]>
>>> Post.objects.filter(tags__1__iexact='Django') >>> Post.objects.filter(tags__1__iexact='Django')
[<Post: First post>] <QuerySet [<Post: First post>]>
>>> Post.objects.filter(tags__276='javascript') >>> Post.objects.filter(tags__276='javascript')
[] <QuerySet []>
.. note:: .. note::
@ -222,10 +222,10 @@ lookups available after the transform do not change. For example::
>>> Post.objects.create(name='Third post', tags=['django', 'python', 'thoughts']) >>> Post.objects.create(name='Third post', tags=['django', 'python', 'thoughts'])
>>> Post.objects.filter(tags__0_1=['thoughts']) >>> Post.objects.filter(tags__0_1=['thoughts'])
[<Post: First post>] <QuerySet [<Post: First post>]>
>>> Post.objects.filter(tags__0_2__contains='thoughts') >>> Post.objects.filter(tags__0_2__contains='thoughts')
[<Post: First post>, <Post: Second post>] <QuerySet [<Post: First post>, <Post: Second post>]>
.. note:: .. note::
@ -320,12 +320,12 @@ To query based on a given key, you simply use that key as the lookup name::
>>> Dog.objects.create(name='Meg', data={'breed': 'collie'}) >>> Dog.objects.create(name='Meg', data={'breed': 'collie'})
>>> Dog.objects.filter(data__breed='collie') >>> Dog.objects.filter(data__breed='collie')
[<Dog: Meg>] <QuerySet [<Dog: Meg>]>
You can chain other lookups after key lookups:: You can chain other lookups after key lookups::
>>> Dog.objects.filter(data__breed__contains='l') >>> Dog.objects.filter(data__breed__contains='l')
[<Dog: Rufus>, <Dog: Meg>] <QuerySet [<Dog: Rufus>, <Dog: Meg>]>
If the key you wish to query by clashes with the name of another lookup, you If the key you wish to query by clashes with the name of another lookup, you
need to use the :lookup:`hstorefield.contains` lookup instead. need to use the :lookup:`hstorefield.contains` lookup instead.
@ -352,10 +352,10 @@ field. It uses the SQL operator ``@>``. For example::
>>> Dog.objects.create(name='Fred', data={}) >>> Dog.objects.create(name='Fred', data={})
>>> Dog.objects.filter(data__contains={'owner': 'Bob'}) >>> Dog.objects.filter(data__contains={'owner': 'Bob'})
[<Dog: Rufus>, <Dog: Meg>] <QuerySet [<Dog: Rufus>, <Dog: Meg>]>
>>> Dog.objects.filter(data__contains={'breed': 'collie'}) >>> Dog.objects.filter(data__contains={'breed': 'collie'})
[<Dog: Meg>] <QuerySet [<Dog: Meg>]>
.. fieldlookup:: hstorefield.contained_by .. fieldlookup:: hstorefield.contained_by
@ -372,10 +372,10 @@ example::
>>> Dog.objects.create(name='Fred', data={}) >>> Dog.objects.create(name='Fred', data={})
>>> Dog.objects.filter(data__contained_by={'breed': 'collie', 'owner': 'Bob'}) >>> Dog.objects.filter(data__contained_by={'breed': 'collie', 'owner': 'Bob'})
[<Dog: Meg>, <Dog: Fred>] <QuerySet [<Dog: Meg>, <Dog: Fred>]>
>>> Dog.objects.filter(data__contained_by={'breed': 'collie'}) >>> Dog.objects.filter(data__contained_by={'breed': 'collie'})
[<Dog: Fred>] <QuerySet [<Dog: Fred>]>
.. fieldlookup:: hstorefield.has_key .. fieldlookup:: hstorefield.has_key
@ -389,7 +389,7 @@ Returns objects where the given key is in the data. Uses the SQL operator
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'}) >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
>>> Dog.objects.filter(data__has_key='owner') >>> Dog.objects.filter(data__has_key='owner')
[<Dog: Meg>] <QuerySet [<Dog: Meg>]>
.. fieldlookup:: hstorefield.has_any_keys .. fieldlookup:: hstorefield.has_any_keys
@ -406,7 +406,7 @@ operator ``?|``. For example::
>>> Dog.objects.create(name='Fred', data={}) >>> Dog.objects.create(name='Fred', data={})
>>> Dog.objects.filter(data__has_any_keys=['owner', 'breed']) >>> Dog.objects.filter(data__has_any_keys=['owner', 'breed'])
[<Dog: Rufus>, <Dog: Meg>] <QuerySet [<Dog: Rufus>, <Dog: Meg>]>
.. fieldlookup:: hstorefield.has_keys .. fieldlookup:: hstorefield.has_keys
@ -420,7 +420,7 @@ Returns objects where all of the given keys are in the data. Uses the SQL operat
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'}) >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
>>> Dog.objects.filter(data__has_keys=['breed', 'owner']) >>> Dog.objects.filter(data__has_keys=['breed', 'owner'])
[<Dog: Meg>] <QuerySet [<Dog: Meg>]>
.. fieldlookup:: hstorefield.keys .. fieldlookup:: hstorefield.keys
@ -437,7 +437,7 @@ in conjunction with lookups on
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'}) >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
>>> Dog.objects.filter(data__keys__overlap=['breed', 'toy']) >>> Dog.objects.filter(data__keys__overlap=['breed', 'toy'])
[<Dog: Rufus>, <Dog: Meg>] <QuerySet [<Dog: Rufus>, <Dog: Meg>]>
.. fieldlookup:: hstorefield.values .. fieldlookup:: hstorefield.values
@ -454,7 +454,7 @@ using in conjunction with lookups on
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'}) >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
>>> Dog.objects.filter(data__values__contains=['collie']) >>> Dog.objects.filter(data__values__contains=['collie'])
[<Dog: Meg>] <QuerySet [<Dog: Meg>]>
JSONField JSONField
--------- ---------
@ -521,18 +521,18 @@ name::
>>> Dog.objects.create(name='Meg', data={'breed': 'collie'}) >>> Dog.objects.create(name='Meg', data={'breed': 'collie'})
>>> Dog.objects.filter(data__breed='collie') >>> Dog.objects.filter(data__breed='collie')
[<Dog: Meg>] <QuerySet [<Dog: Meg>]>
Multiple keys can be chained together to form a path lookup:: Multiple keys can be chained together to form a path lookup::
>>> Dog.objects.filter(data__owner__name='Bob') >>> Dog.objects.filter(data__owner__name='Bob')
[<Dog: Rufus>] <QuerySet [<QuerySet <Dog: Rufus>]>
If the key is an integer, it will be interpreted as an index lookup in an If the key is an integer, it will be interpreted as an index lookup in an
array:: array::
>>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy') >>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy')
[<Dog: Rufus>] <QuerySet [<Dog: Rufus>]>
If the key you wish to query by clashes with the name of another lookup, use If the key you wish to query by clashes with the name of another lookup, use
the :lookup:`jsonfield.contains` lookup instead. the :lookup:`jsonfield.contains` lookup instead.
@ -673,7 +673,7 @@ contains
'''''''' ''''''''
>>> Event.objects.filter(ages__contains=NumericRange(4, 5)) >>> Event.objects.filter(ages__contains=NumericRange(4, 5))
[<Event: Soft play>] <QuerySet [<Event: Soft play>]>
.. fieldlookup:: rangefield.contained_by .. fieldlookup:: rangefield.contained_by
@ -681,7 +681,7 @@ contained_by
'''''''''''' ''''''''''''
>>> Event.objects.filter(ages__contained_by=NumericRange(0, 15)) >>> Event.objects.filter(ages__contained_by=NumericRange(0, 15))
[<Event: Soft play>] <QuerySet [<Event: Soft play>]>
.. versionadded 1.9 .. versionadded 1.9
@ -697,7 +697,7 @@ contained_by
... timezone.now() - datetime.timedelta(hours=1), ... timezone.now() - datetime.timedelta(hours=1),
... timezone.now() + datetime.timedelta(hours=1), ... timezone.now() + datetime.timedelta(hours=1),
... ) ... )
[<Event: Soft play>] <QuerySet [<Event: Soft play>]>
.. fieldlookup:: rangefield.overlap .. fieldlookup:: rangefield.overlap
@ -705,7 +705,7 @@ overlap
''''''' '''''''
>>> Event.objects.filter(ages__overlap=NumericRange(8, 12)) >>> Event.objects.filter(ages__overlap=NumericRange(8, 12))
[<Event: Soft play>] <QuerySet [<Event: Soft play>]>
Comparison functions Comparison functions
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
@ -726,7 +726,7 @@ all the points in the returned range are less than all those in the passed
range. range.
>>> Event.objects.filter(ages__fully_lt=NumericRange(11, 15)) >>> Event.objects.filter(ages__fully_lt=NumericRange(11, 15))
[<Event: Soft play>] <QuerySet [<Event: Soft play>]>
.. fieldlookup:: rangefield.fully_gt .. fieldlookup:: rangefield.fully_gt
@ -738,7 +738,7 @@ the all the points in the returned range are greater than all those in the
passed range. passed range.
>>> Event.objects.filter(ages__fully_gt=NumericRange(11, 15)) >>> Event.objects.filter(ages__fully_gt=NumericRange(11, 15))
[<Event: Pub trip>] <QuerySet [<Event: Pub trip>]>
.. fieldlookup:: rangefield.not_lt .. fieldlookup:: rangefield.not_lt
@ -750,7 +750,7 @@ is the lower bound of the returned range is at least the lower bound of the
passed range. passed range.
>>> Event.objects.filter(ages__not_lt=NumericRange(0, 15)) >>> Event.objects.filter(ages__not_lt=NumericRange(0, 15))
[<Event: Soft play>, <Event: Pub trip>] <QuerySet [<Event: Soft play>, <Event: Pub trip>]>
.. fieldlookup:: rangefield.not_gt .. fieldlookup:: rangefield.not_gt
@ -762,7 +762,7 @@ is the upper bound of the returned range is at most the upper bound of the
passed range. passed range.
>>> Event.objects.filter(ages__not_gt=NumericRange(3, 10)) >>> Event.objects.filter(ages__not_gt=NumericRange(3, 10))
[<Event: Soft play>] <QuerySet [<Event: Soft play>]>
.. fieldlookup:: rangefield.adjacent_to .. fieldlookup:: rangefield.adjacent_to
@ -772,7 +772,7 @@ adjacent_to
The returned ranges share a bound with the passed range. The returned ranges share a bound with the passed range.
>>> Event.objects.filter(ages__adjacent_to=NumericRange(10, 21)) >>> Event.objects.filter(ages__adjacent_to=NumericRange(10, 21))
[<Event: Soft play>, <Event: Pub trip>] <QuerySet [<Event: Soft play>, <Event: Pub trip>]>
Querying using the bounds Querying using the bounds
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
@ -789,7 +789,7 @@ Returned objects have the given lower bound. Can be chained to valid lookups
for the base field. for the base field.
>>> Event.objects.filter(ages__startswith=21) >>> Event.objects.filter(ages__startswith=21)
[<Event: Pub trip>] <QuerySet [<Event: Pub trip>]>
.. fieldlookup:: rangefield.endswith .. fieldlookup:: rangefield.endswith
@ -800,7 +800,7 @@ Returned objects have the given upper bound. Can be chained to valid lookups
for the base field. for the base field.
>>> Event.objects.filter(ages__endswith=10) >>> Event.objects.filter(ages__endswith=10)
[<Event: Soft play>] <QuerySet [<Event: Soft play>]>
.. fieldlookup:: rangefield.isempty .. fieldlookup:: rangefield.isempty
@ -811,7 +811,7 @@ Returned objects are empty ranges. Can be chained to valid lookups for a
:class:`~django.db.models.BooleanField`. :class:`~django.db.models.BooleanField`.
>>> Event.objects.filter(ages__isempty=True) >>> Event.objects.filter(ages__isempty=True)
[] <QuerySet []>
Defining your own range types Defining your own range types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -28,4 +28,4 @@ Usage example::
>>> from django.contrib.postgres.functions import TransactionNow >>> from django.contrib.postgres.functions import TransactionNow
>>> Article.objects.filter(published__lte=TransactionNow()) >>> Article.objects.filter(published__lte=TransactionNow())
[<Article: How to Django>] <QuerySet [<Article: How to Django>]>

View File

@ -226,7 +226,7 @@ Usage example::
>>> from django.db.models.functions import Now >>> from django.db.models.functions import Now
>>> Article.objects.filter(published__lte=Now()) >>> Article.objects.filter(published__lte=Now())
[<Article: How to Django>] <QuerySet [<Article: How to Django>]>
.. admonition:: PostgreSQL considerations .. admonition:: PostgreSQL considerations

View File

@ -513,11 +513,11 @@ objects::
# This list contains a Blog object. # This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles') >>> Blog.objects.filter(name__startswith='Beatles')
[<Blog: Beatles Blog>] <QuerySet [<Blog: Beatles Blog>]>
# This list contains a dictionary. # This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values() >>> Blog.objects.filter(name__startswith='Beatles').values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}] <QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
The ``values()`` method takes optional positional arguments, ``*fields``, which The ``values()`` method takes optional positional arguments, ``*fields``, which
specify field names to which the ``SELECT`` should be limited. If you specify specify field names to which the ``SELECT`` should be limited. If you specify
@ -528,9 +528,9 @@ contain a key and value for every field in the database table.
Example:: Example::
>>> Blog.objects.values() >>> Blog.objects.values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}], <QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
>>> Blog.objects.values('id', 'name') >>> Blog.objects.values('id', 'name')
[{'id': 1, 'name': 'Beatles Blog'}] <QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>
A few subtleties that are worth mentioning: A few subtleties that are worth mentioning:
@ -546,13 +546,13 @@ A few subtleties that are worth mentioning:
For example:: For example::
>>> Entry.objects.values() >>> Entry.objects.values()
[{'blog_id': 1, 'headline': 'First Entry', ...}, ...] <QuerySet [{'blog_id': 1, 'headline': 'First Entry', ...}, ...]>
>>> Entry.objects.values('blog') >>> Entry.objects.values('blog')
[{'blog': 1}, ...] <QuerySet [{'blog': 1}, ...]>
>>> Entry.objects.values('blog_id') >>> Entry.objects.values('blog_id')
[{'blog_id': 1}, ...] <QuerySet [{'blog_id': 1}, ...]>
* When using ``values()`` together with :meth:`distinct()`, be aware that * When using ``values()`` together with :meth:`distinct()`, be aware that
ordering can affect the results. See the note in :meth:`distinct` for ordering can affect the results. See the note in :meth:`distinct` for
@ -585,9 +585,9 @@ individualism.
You can also refer to fields on related models with reverse relations through You can also refer to fields on related models with reverse relations through
``OneToOneField``, ``ForeignKey`` and ``ManyToManyField`` attributes:: ``OneToOneField``, ``ForeignKey`` and ``ManyToManyField`` attributes::
Blog.objects.values('name', 'entry__headline') >>> Blog.objects.values('name', 'entry__headline')
[{'name': 'My blog', 'entry__headline': 'An entry'}, <QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'},
{'name': 'My blog', 'entry__headline': 'Another entry'}, ...] {'name': 'My blog', 'entry__headline': 'Another entry'}, ...]>
.. warning:: .. warning::
@ -717,7 +717,7 @@ is an instance of ``EmptyQuerySet``.
Examples:: Examples::
>>> Entry.objects.none() >>> Entry.objects.none()
[] <QuerySet []>
>>> from django.db.models.query import EmptyQuerySet >>> from django.db.models.query import EmptyQuerySet
>>> isinstance(Entry.objects.none(), EmptyQuerySet) >>> isinstance(Entry.objects.none(), EmptyQuerySet)
True True
@ -3015,11 +3015,11 @@ as the string based lookups passed to
:meth:`~django.db.models.query.QuerySet.prefetch_related()`. For example: :meth:`~django.db.models.query.QuerySet.prefetch_related()`. For example:
>>> Question.objects.prefetch_related(Prefetch('choice_set')).get().choice_set.all() >>> Question.objects.prefetch_related(Prefetch('choice_set')).get().choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
# This will only execute two queries regardless of the number of Question # This will only execute two queries regardless of the number of Question
# and Choice objects. # and Choice objects.
>>> Question.objects.prefetch_related(Prefetch('choice_set')).all() >>> Question.objects.prefetch_related(Prefetch('choice_set')).all()
[<Question: Question object>] <QuerySet [<Question: Question object>]>
The ``queryset`` argument supplies a base ``QuerySet`` for the given lookup. The ``queryset`` argument supplies a base ``QuerySet`` for the given lookup.
This is useful to further filter down the prefetch operation, or to call This is useful to further filter down the prefetch operation, or to call
@ -3028,19 +3028,19 @@ relation, hence reducing the number of queries even further:
>>> voted_choices = Choice.objects.filter(votes__gt=0) >>> voted_choices = Choice.objects.filter(votes__gt=0)
>>> voted_choices >>> voted_choices
[<Choice: The sky>] <QuerySet [<Choice: The sky>]>
>>> prefetch = Prefetch('choice_set', queryset=voted_choices) >>> prefetch = Prefetch('choice_set', queryset=voted_choices)
>>> Question.objects.prefetch_related(prefetch).get().choice_set.all() >>> Question.objects.prefetch_related(prefetch).get().choice_set.all()
[<Choice: The sky>] <QuerySet [<Choice: The sky>]>
The ``to_attr`` argument sets the result of the prefetch operation to a custom The ``to_attr`` argument sets the result of the prefetch operation to a custom
attribute: attribute:
>>> prefetch = Prefetch('choice_set', queryset=voted_choices, to_attr='voted_choices') >>> prefetch = Prefetch('choice_set', queryset=voted_choices, to_attr='voted_choices')
>>> Question.objects.prefetch_related(prefetch).get().voted_choices >>> Question.objects.prefetch_related(prefetch).get().voted_choices
[<Choice: The sky>] <QuerySet [<Choice: The sky>]>
>>> Question.objects.prefetch_related(prefetch).get().choice_set.all() >>> Question.objects.prefetch_related(prefetch).get().choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
.. note:: .. note::

View File

@ -219,7 +219,8 @@ Database backend API
Miscellaneous Miscellaneous
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
* ... * The ``repr()`` of a ``QuerySet`` is wrapped in ```<QuerySet >`` to
disambiguate it from a plain list when debugging.
.. _deprecated-features-1.10: .. _deprecated-features-1.10:

View File

@ -79,7 +79,7 @@ In a hurry? Here's how to do common aggregate queries, assuming the models above
>>> from django.db.models import Count >>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book')) >>> pubs = Publisher.objects.annotate(num_books=Count('book'))
>>> pubs >>> pubs
[<Publisher BaloneyPress>, <Publisher SalamiPress>, ...] <QuerySet [<Publisher: BaloneyPress>, <Publisher: SalamiPress>, ...]>
>>> pubs[0].num_books >>> pubs[0].num_books
73 73

View File

@ -93,36 +93,36 @@ Create and add a ``Publication`` to an ``Article`` in one step using
``Article`` objects have access to their related ``Publication`` objects:: ``Article`` objects have access to their related ``Publication`` objects::
>>> a1.publications.all() >>> a1.publications.all()
[<Publication: The Python Journal>] <QuerySet [<Publication: The Python Journal>]>
>>> a2.publications.all() >>> a2.publications.all()
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]>
``Publication`` objects have access to their related ``Article`` objects:: ``Publication`` objects have access to their related ``Article`` objects::
>>> p2.article_set.all() >>> p2.article_set.all()
[<Article: NASA uses Python>] <QuerySet [<Article: NASA uses Python>]>
>>> p1.article_set.all() >>> p1.article_set.all()
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]>
>>> Publication.objects.get(id=4).article_set.all() >>> Publication.objects.get(id=4).article_set.all()
[<Article: NASA uses Python>] <QuerySet [<Article: NASA uses Python>]>
Many-to-many relationships can be queried using :ref:`lookups across Many-to-many relationships can be queried using :ref:`lookups across
relationships <lookups-that-span-relationships>`:: relationships <lookups-that-span-relationships>`::
>>> Article.objects.filter(publications__id=1) >>> Article.objects.filter(publications__id=1)
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]>
>>> Article.objects.filter(publications__pk=1) >>> Article.objects.filter(publications__pk=1)
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]>
>>> Article.objects.filter(publications=1) >>> Article.objects.filter(publications=1)
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]>
>>> Article.objects.filter(publications=p1) >>> Article.objects.filter(publications=p1)
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]>
>>> Article.objects.filter(publications__title__startswith="Science") >>> Article.objects.filter(publications__title__startswith="Science")
[<Article: NASA uses Python>, <Article: NASA uses Python>] <QuerySet [<Article: NASA uses Python>, <Article: NASA uses Python>]>
>>> Article.objects.filter(publications__title__startswith="Science").distinct() >>> Article.objects.filter(publications__title__startswith="Science").distinct()
[<Article: NASA uses Python>] <QuerySet [<Article: NASA uses Python>]>
The :meth:`~django.db.models.query.QuerySet.count` function respects The :meth:`~django.db.models.query.QuerySet.count` function respects
:meth:`~django.db.models.query.QuerySet.distinct` as well:: :meth:`~django.db.models.query.QuerySet.distinct` as well::
@ -134,57 +134,57 @@ The :meth:`~django.db.models.query.QuerySet.count` function respects
1 1
>>> Article.objects.filter(publications__in=[1,2]).distinct() >>> Article.objects.filter(publications__in=[1,2]).distinct()
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]>
>>> Article.objects.filter(publications__in=[p1,p2]).distinct() >>> Article.objects.filter(publications__in=[p1,p2]).distinct()
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] <QuerySet [<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 Reverse m2m queries are supported (i.e., starting at the table that doesn't have
a :class:`~django.db.models.ManyToManyField`):: a :class:`~django.db.models.ManyToManyField`)::
>>> Publication.objects.filter(id=1) >>> Publication.objects.filter(id=1)
[<Publication: The Python Journal>] <QuerySet [<Publication: The Python Journal>]>
>>> Publication.objects.filter(pk=1) >>> Publication.objects.filter(pk=1)
[<Publication: The Python Journal>] <QuerySet [<Publication: The Python Journal>]>
>>> Publication.objects.filter(article__headline__startswith="NASA") >>> Publication.objects.filter(article__headline__startswith="NASA")
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]>
>>> Publication.objects.filter(article__id=1) >>> Publication.objects.filter(article__id=1)
[<Publication: The Python Journal>] <QuerySet [<Publication: The Python Journal>]>
>>> Publication.objects.filter(article__pk=1) >>> Publication.objects.filter(article__pk=1)
[<Publication: The Python Journal>] <QuerySet [<Publication: The Python Journal>]>
>>> Publication.objects.filter(article=1) >>> Publication.objects.filter(article=1)
[<Publication: The Python Journal>] <QuerySet [<Publication: The Python Journal>]>
>>> Publication.objects.filter(article=a1) >>> Publication.objects.filter(article=a1)
[<Publication: The Python Journal>] <QuerySet [<Publication: The Python Journal>]>
>>> Publication.objects.filter(article__in=[1,2]).distinct() >>> Publication.objects.filter(article__in=[1,2]).distinct()
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]>
>>> Publication.objects.filter(article__in=[a1,a2]).distinct() >>> Publication.objects.filter(article__in=[a1,a2]).distinct()
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] <QuerySet [<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 Excluding a related item works as you would expect, too (although the SQL
involved is a little complex):: involved is a little complex)::
>>> Article.objects.exclude(publications=p2) >>> Article.objects.exclude(publications=p2)
[<Article: Django lets you build Web apps easily>] <QuerySet [<Article: Django lets you build Web apps easily>]>
If we delete a ``Publication``, its ``Articles`` won't be able to access it:: If we delete a ``Publication``, its ``Articles`` won't be able to access it::
>>> p1.delete() >>> p1.delete()
>>> Publication.objects.all() >>> Publication.objects.all()
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>] <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>]>
>>> a1 = Article.objects.get(pk=1) >>> a1 = Article.objects.get(pk=1)
>>> a1.publications.all() >>> a1.publications.all()
[] <QuerySet []>
If we delete an ``Article``, its ``Publications`` won't be able to access it:: If we delete an ``Article``, its ``Publications`` won't be able to access it::
>>> a2.delete() >>> a2.delete()
>>> Article.objects.all() >>> Article.objects.all()
[<Article: Django lets you build Web apps easily>] <QuerySet [<Article: Django lets you build Web apps easily>]>
>>> p2.article_set.all() >>> p2.article_set.all()
[] <QuerySet []>
Adding via the 'other' end of an m2m:: Adding via the 'other' end of an m2m::
@ -192,61 +192,61 @@ Adding via the 'other' end of an m2m::
>>> a4.save() >>> a4.save()
>>> p2.article_set.add(a4) >>> p2.article_set.add(a4)
>>> p2.article_set.all() >>> p2.article_set.all()
[<Article: NASA finds intelligent life on Earth>] <QuerySet [<Article: NASA finds intelligent life on Earth>]>
>>> a4.publications.all() >>> a4.publications.all()
[<Publication: Science News>] <QuerySet [<Publication: Science News>]>
Adding via the other end using keywords:: Adding via the other end using keywords::
>>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders') >>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders')
>>> p2.article_set.all() >>> p2.article_set.all()
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>] <QuerySet [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]>
>>> a5 = p2.article_set.all()[1] >>> a5 = p2.article_set.all()[1]
>>> a5.publications.all() >>> a5.publications.all()
[<Publication: Science News>] <QuerySet [<Publication: Science News>]>
Removing ``Publication`` from an ``Article``:: Removing ``Publication`` from an ``Article``::
>>> a4.publications.remove(p2) >>> a4.publications.remove(p2)
>>> p2.article_set.all() >>> p2.article_set.all()
[<Article: Oxygen-free diet works wonders>] <QuerySet [<Article: Oxygen-free diet works wonders>]>
>>> a4.publications.all() >>> a4.publications.all()
[] <QuerySet []>
And from the other end:: And from the other end::
>>> p2.article_set.remove(a5) >>> p2.article_set.remove(a5)
>>> p2.article_set.all() >>> p2.article_set.all()
[] <QuerySet []>
>>> a5.publications.all() >>> a5.publications.all()
[] <QuerySet []>
Relation sets can be assigned. Assignment clears any existing set members:: Relation sets can be assigned. Assignment clears any existing set members::
>>> a4.publications.all() >>> a4.publications.all()
[<Publication: Science News>] <QuerySet [<Publication: Science News>]>
>>> a4.publications = [p3] >>> a4.publications = [p3]
>>> a4.publications.all() >>> a4.publications.all()
[<Publication: Science Weekly>] <QuerySet [<Publication: Science Weekly>]>
Relation sets can be cleared:: Relation sets can be cleared::
>>> p2.article_set.clear() >>> p2.article_set.clear()
>>> p2.article_set.all() >>> p2.article_set.all()
[] <QuerySet []>
And you can clear from the other end:: And you can clear from the other end::
>>> p2.article_set.add(a4, a5) >>> p2.article_set.add(a4, a5)
>>> p2.article_set.all() >>> p2.article_set.all()
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>] <QuerySet [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]>
>>> a4.publications.all() >>> a4.publications.all()
[<Publication: Science News>, <Publication: Science Weekly>] <QuerySet [<Publication: Science News>, <Publication: Science Weekly>]>
>>> a4.publications.clear() >>> a4.publications.clear()
>>> a4.publications.all() >>> a4.publications.all()
[] <QuerySet []>
>>> p2.article_set.all() >>> p2.article_set.all()
[<Article: Oxygen-free diet works wonders>] <QuerySet [<Article: Oxygen-free diet works wonders>]>
Recreate the ``Article`` and ``Publication`` we have deleted:: Recreate the ``Article`` and ``Publication`` we have deleted::
@ -261,17 +261,17 @@ go::
>>> Publication.objects.filter(title__startswith='Science').delete() >>> Publication.objects.filter(title__startswith='Science').delete()
>>> Publication.objects.all() >>> Publication.objects.all()
[<Publication: Highlights for Children>, <Publication: The Python Journal>] <QuerySet [<Publication: Highlights for Children>, <Publication: The Python Journal>]>
>>> Article.objects.all() >>> 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>] <QuerySet [<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() >>> a2.publications.all()
[<Publication: The Python Journal>] <QuerySet [<Publication: The Python Journal>]>
Bulk delete some articles - references to deleted objects should go:: Bulk delete some articles - references to deleted objects should go::
>>> q = Article.objects.filter(headline__startswith='Django') >>> q = Article.objects.filter(headline__startswith='Django')
>>> print(q) >>> print(q)
[<Article: Django lets you build Web apps easily>] <QuerySet [<Article: Django lets you build Web apps easily>]>
>>> q.delete() >>> q.delete()
After the :meth:`~django.db.models.query.QuerySet.delete`, the After the :meth:`~django.db.models.query.QuerySet.delete`, the
@ -279,9 +279,9 @@ After the :meth:`~django.db.models.query.QuerySet.delete`, the
referenced objects should be gone:: referenced objects should be gone::
>>> print(q) >>> print(q)
[] <QuerySet []>
>>> p1.article_set.all() >>> p1.article_set.all()
[<Article: NASA uses Python>] <QuerySet [<Article: NASA uses Python>]>
An alternate to calling An alternate to calling
:meth:`~django.db.models.fields.related.RelatedManager.clear` is to assign the :meth:`~django.db.models.fields.related.RelatedManager.clear` is to assign the
@ -289,11 +289,11 @@ empty set::
>>> p1.article_set = [] >>> p1.article_set = []
>>> p1.article_set.all() >>> p1.article_set.all()
[] <QuerySet []>
>>> a2.publications = [p1, new_publication] >>> a2.publications = [p1, new_publication]
>>> a2.publications.all() >>> a2.publications.all()
[<Publication: Highlights for Children>, <Publication: The Python Journal>] <QuerySet [<Publication: Highlights for Children>, <Publication: The Python Journal>]>
>>> a2.publications = [] >>> a2.publications = []
>>> a2.publications.all() >>> a2.publications.all()
[] <QuerySet []>

View File

@ -90,7 +90,7 @@ Create a new article, and add it to the article set::
>>> new_article2.reporter.id >>> new_article2.reporter.id
1 1
>>> r.article_set.all() >>> r.article_set.all()
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] <QuerySet [<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:: Add the same article to a different article set - check that it moves::
@ -108,9 +108,9 @@ Adding an object of the wrong type raises TypeError::
TypeError: 'Article' instance expected TypeError: 'Article' instance expected
>>> r.article_set.all() >>> r.article_set.all()
[<Article: John's second story>, <Article: This is a test>] <QuerySet [<Article: John's second story>, <Article: This is a test>]>
>>> r2.article_set.all() >>> r2.article_set.all()
[<Article: Paul's story>] <QuerySet [<Article: Paul's story>]>
>>> r.article_set.count() >>> r.article_set.count()
2 2
@ -126,56 +126,56 @@ Use double underscores to separate relationships.
This works as many levels deep as you want. There's no limit. For example:: This works as many levels deep as you want. There's no limit. For example::
>>> r.article_set.filter(headline__startswith='This') >>> r.article_set.filter(headline__startswith='This')
[<Article: This is a test>] <QuerySet [<Article: This is a test>]>
# Find all Articles for any Reporter whose first name is "John". # Find all Articles for any Reporter whose first name is "John".
>>> Article.objects.filter(reporter__first_name='John') >>> Article.objects.filter(reporter__first_name='John')
[<Article: John's second story>, <Article: This is a test>] <QuerySet [<Article: John's second story>, <Article: This is a test>]>
Exact match is implied here:: Exact match is implied here::
>>> Article.objects.filter(reporter__first_name='John') >>> Article.objects.filter(reporter__first_name='John')
[<Article: John's second story>, <Article: This is a test>] <QuerySet [<Article: John's second story>, <Article: This is a test>]>
Query twice over the related field. This translates to an AND condition in the Query twice over the related field. This translates to an AND condition in the
WHERE clause:: WHERE clause::
>>> Article.objects.filter(reporter__first_name='John', reporter__last_name='Smith') >>> Article.objects.filter(reporter__first_name='John', reporter__last_name='Smith')
[<Article: John's second story>, <Article: This is a test>] <QuerySet [<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 For the related lookup you can supply a primary key value or pass the related
object explicitly:: object explicitly::
>>> Article.objects.filter(reporter__pk=1) >>> Article.objects.filter(reporter__pk=1)
[<Article: John's second story>, <Article: This is a test>] <QuerySet [<Article: John's second story>, <Article: This is a test>]>
>>> Article.objects.filter(reporter=1) >>> Article.objects.filter(reporter=1)
[<Article: John's second story>, <Article: This is a test>] <QuerySet [<Article: John's second story>, <Article: This is a test>]>
>>> Article.objects.filter(reporter=r) >>> Article.objects.filter(reporter=r)
[<Article: John's second story>, <Article: This is a test>] <QuerySet [<Article: John's second story>, <Article: This is a test>]>
>>> Article.objects.filter(reporter__in=[1,2]).distinct() >>> Article.objects.filter(reporter__in=[1,2]).distinct()
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] <QuerySet [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]>
>>> Article.objects.filter(reporter__in=[r,r2]).distinct() >>> Article.objects.filter(reporter__in=[r,r2]).distinct()
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] <QuerySet [<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:: 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.objects.filter(reporter__in=Reporter.objects.filter(first_name='John')).distinct()
[<Article: John's second story>, <Article: This is a test>] <QuerySet [<Article: John's second story>, <Article: This is a test>]>
Querying in the opposite direction:: Querying in the opposite direction::
>>> Reporter.objects.filter(article__pk=1) >>> Reporter.objects.filter(article__pk=1)
[<Reporter: John Smith>] <QuerySet [<Reporter: John Smith>]>
>>> Reporter.objects.filter(article=1) >>> Reporter.objects.filter(article=1)
[<Reporter: John Smith>] <QuerySet [<Reporter: John Smith>]>
>>> Reporter.objects.filter(article=a) >>> Reporter.objects.filter(article=a)
[<Reporter: John Smith>] <QuerySet [<Reporter: John Smith>]>
>>> Reporter.objects.filter(article__headline__startswith='This') >>> Reporter.objects.filter(article__headline__startswith='This')
[<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>] <QuerySet [<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]>
>>> Reporter.objects.filter(article__headline__startswith='This').distinct() >>> Reporter.objects.filter(article__headline__startswith='This').distinct()
[<Reporter: John Smith>] <QuerySet [<Reporter: John Smith>]>
Counting in the opposite direction works in conjunction with distinct():: Counting in the opposite direction works in conjunction with distinct()::
@ -187,30 +187,30 @@ Counting in the opposite direction works in conjunction with distinct()::
Queries can go round in circles:: Queries can go round in circles::
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John') >>> Reporter.objects.filter(article__reporter__first_name__startswith='John')
[<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>] <QuerySet [<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]>
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct() >>> Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct()
[<Reporter: John Smith>] <QuerySet [<Reporter: John Smith>]>
>>> Reporter.objects.filter(article__reporter=r).distinct() >>> Reporter.objects.filter(article__reporter=r).distinct()
[<Reporter: John Smith>] <QuerySet [<Reporter: John Smith>]>
If you delete a reporter, his articles will be deleted (assuming that the 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 ForeignKey was defined with :attr:`django.db.models.ForeignKey.on_delete` set to
``CASCADE``, which is the default):: ``CASCADE``, which is the default)::
>>> Article.objects.all() >>> Article.objects.all()
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] <QuerySet [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]>
>>> Reporter.objects.order_by('first_name') >>> Reporter.objects.order_by('first_name')
[<Reporter: John Smith>, <Reporter: Paul Jones>] <QuerySet [<Reporter: John Smith>, <Reporter: Paul Jones>]>
>>> r2.delete() >>> r2.delete()
>>> Article.objects.all() >>> Article.objects.all()
[<Article: John's second story>, <Article: This is a test>] <QuerySet [<Article: John's second story>, <Article: This is a test>]>
>>> Reporter.objects.order_by('first_name') >>> Reporter.objects.order_by('first_name')
[<Reporter: John Smith>] <QuerySet [<Reporter: John Smith>]>
You can delete using a JOIN in the query:: You can delete using a JOIN in the query::
>>> Reporter.objects.filter(article__headline__startswith='This').delete() >>> Reporter.objects.filter(article__headline__startswith='This').delete()
>>> Reporter.objects.all() >>> Reporter.objects.all()
[] <QuerySet []>
>>> Article.objects.all() >>> Article.objects.all()
[] <QuerySet []>

View File

@ -106,13 +106,13 @@ that there are two restaurants - Ace Hardware the Restaurant was created in the
call to r.place = p2:: call to r.place = p2::
>>> Restaurant.objects.all() >>> Restaurant.objects.all()
[<Restaurant: Demon Dogs the restaurant>, <Restaurant: Ace Hardware the restaurant>] <QuerySet [<Restaurant: Demon Dogs the restaurant>, <Restaurant: Ace Hardware the restaurant>]>
Place.objects.all() returns all Places, regardless of whether they have Place.objects.all() returns all Places, regardless of whether they have
Restaurants:: Restaurants::
>>> Place.objects.order_by('name') >>> Place.objects.order_by('name')
[<Place: Ace Hardware the place>, <Place: Demon Dogs the place>] <QuerySet [<Place: Ace Hardware the place>, <Place: Demon Dogs the place>]>
You can query the models using :ref:`lookups across relationships <lookups-that-span-relationships>`:: You can query the models using :ref:`lookups across relationships <lookups-that-span-relationships>`::
@ -121,9 +121,9 @@ You can query the models using :ref:`lookups across relationships <lookups-that-
>>> Restaurant.objects.get(place__pk=1) >>> Restaurant.objects.get(place__pk=1)
<Restaurant: Demon Dogs the restaurant> <Restaurant: Demon Dogs the restaurant>
>>> Restaurant.objects.filter(place__name__startswith="Demon") >>> Restaurant.objects.filter(place__name__startswith="Demon")
[<Restaurant: Demon Dogs the restaurant>] <QuerySet [<Restaurant: Demon Dogs the restaurant>]>
>>> Restaurant.objects.exclude(place__address__contains="Ashland") >>> Restaurant.objects.exclude(place__address__contains="Ashland")
[<Restaurant: Demon Dogs the restaurant>] <QuerySet [<Restaurant: Demon Dogs the restaurant>]>
This of course works in reverse:: This of course works in reverse::
@ -146,6 +146,6 @@ Add a Waiter to the Restaurant::
Query the waiters:: Query the waiters::
>>> Waiter.objects.filter(restaurant__place=p1) >>> Waiter.objects.filter(restaurant__place=p1)
[<Waiter: Joe the waiter at Demon Dogs the restaurant>] <QuerySet [<Waiter: Joe the waiter at Demon Dogs the restaurant>]>
>>> Waiter.objects.filter(restaurant__place__name__startswith="Demon") >>> Waiter.objects.filter(restaurant__place__name__startswith="Demon")
[<Waiter: Joe the waiter at Demon Dogs the restaurant>] <QuerySet [<Waiter: Joe the waiter at Demon Dogs the restaurant>]>

View File

@ -501,14 +501,14 @@ the intermediate model::
... invite_reason="Needed a new drummer.") ... invite_reason="Needed a new drummer.")
>>> m1.save() >>> m1.save()
>>> beatles.members.all() >>> beatles.members.all()
[<Person: Ringo Starr>] <QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all() >>> ringo.group_set.all()
[<Group: The Beatles>] <QuerySet [<Group: The Beatles>]>
>>> m2 = Membership.objects.create(person=paul, group=beatles, >>> m2 = Membership.objects.create(person=paul, group=beatles,
... date_joined=date(1960, 8, 1), ... date_joined=date(1960, 8, 1),
... invite_reason="Wanted to form a band.") ... invite_reason="Wanted to form a band.")
>>> beatles.members.all() >>> beatles.members.all()
[<Person: Ringo Starr>, <Person: Paul McCartney>] <QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>
Unlike normal many-to-many fields, you *can't* use ``add``, ``create``, Unlike normal many-to-many fields, you *can't* use ``add``, ``create``,
or assignment (i.e., ``beatles.members = [...]``) to create relationships:: or assignment (i.e., ``beatles.members = [...]``) to create relationships::
@ -537,7 +537,7 @@ used to remove all many-to-many relationships for an instance::
>>> beatles.members.clear() >>> beatles.members.clear()
>>> # Note that this deletes the intermediate model instances >>> # Note that this deletes the intermediate model instances
>>> Membership.objects.all() >>> Membership.objects.all()
[] <QuerySet []>
Once you have established the many-to-many relationships by creating instances Once you have established the many-to-many relationships by creating instances
of your intermediate model, you can issue queries. Just as with normal of your intermediate model, you can issue queries. Just as with normal
@ -546,7 +546,7 @@ many-to-many-related model::
# Find all the groups with a member whose name starts with 'Paul' # Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(members__name__startswith='Paul') >>> Group.objects.filter(members__name__startswith='Paul')
[<Group: The Beatles>] <QuerySet [<Group: The Beatles>]>
As you are using an intermediate model, you can also query on its attributes:: As you are using an intermediate model, you can also query on its attributes::
@ -554,7 +554,7 @@ As you are using an intermediate model, you can also query on its attributes::
>>> Person.objects.filter( >>> Person.objects.filter(
... group__name='The Beatles', ... group__name='The Beatles',
... membership__date_joined__gt=date(1961,1,1)) ... membership__date_joined__gt=date(1961,1,1))
[<Person: Ringo Starr] <QuerySet [<Person: Ringo Starr]>
If you need to access a membership's information you may do so by directly If you need to access a membership's information you may do so by directly
querying the ``Membership`` model:: querying the ``Membership`` model::

View File

@ -912,7 +912,7 @@ extra forms displayed.
``max_num`` does not prevent existing objects from being displayed:: ``max_num`` does not prevent existing objects from being displayed::
>>> Author.objects.order_by('name') >>> Author.objects.order_by('name')
[<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>] <QuerySet [<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>]>
>>> AuthorFormSet = modelformset_factory(Author, fields=('name',), max_num=1) >>> AuthorFormSet = modelformset_factory(Author, fields=('name',), max_num=1)
>>> formset = AuthorFormSet(queryset=Author.objects.order_by('name')) >>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))

View File

@ -800,11 +800,12 @@ class NaturalKeyFixtureTests(TestCase):
verbosity=0, verbosity=0,
) )
books = Book.objects.all() books = Book.objects.all()
self.assertEqual( self.assertQuerysetEqual(
books.__repr__(), books, [
"[<Book: Cryptonomicon by Neal Stephenson (available at Amazon, Borders)>, " "<Book: Cryptonomicon by Neal Stephenson (available at Amazon, Borders)>",
"<Book: Ender's Game by Orson Scott Card (available at Collins Bookstore)>, " "<Book: Ender's Game by Orson Scott Card (available at Collins Bookstore)>",
"<Book: Permutation City by Greg Egan (available at Angus and Robertson)>]" "<Book: Permutation City by Greg Egan (available at Angus and Robertson)>",
]
) )

View File

@ -47,7 +47,7 @@ class NullQueriesTests(TestCase):
# Related managers use __exact=None implicitly if the object hasn't been saved. # Related managers use __exact=None implicitly if the object hasn't been saved.
p2 = Poll(question="How?") p2 = Poll(question="How?")
self.assertEqual(repr(p2.choice_set.all()), '[]') self.assertEqual(repr(p2.choice_set.all()), '<QuerySet []>')
def test_reverse_relations(self): def test_reverse_relations(self):
""" """

View File

@ -78,7 +78,9 @@ class StringLookupTests(TestCase):
""" """
a = Article(name='IP test', text='The body', submitted_from='192.0.2.100') a = Article(name='IP test', text='The body', submitted_from='192.0.2.100')
a.save() a.save()
self.assertEqual(repr(Article.objects.filter(submitted_from__contains='192.0.2')), self.assertQuerysetEqual(
repr([a])) Article.objects.filter(submitted_from__contains='192.0.2'),
[a], lambda x: x
)
# Test that the searches do not match the subnet mask (/32 in this case) # Test that the searches do not match the subnet mask (/32 in this case)
self.assertEqual(Article.objects.filter(submitted_from__contains='32').count(), 0) self.assertEqual(Article.objects.filter(submitted_from__contains='32').count(), 0)