mirror of https://github.com/django/django.git
Fixed #32518 -- Doc'd that QuerySet.contains() should not be overused.
Thanks Tim McCurrach for the idea.
This commit is contained in:
parent
e3f34b1f09
commit
d70b4bea18
|
@ -261,44 +261,52 @@ But:
|
||||||
|
|
||||||
.. _overuse_of_count_and_exists:
|
.. _overuse_of_count_and_exists:
|
||||||
|
|
||||||
Don't overuse ``count()`` and ``exists()``
|
Don't overuse ``contains()``, ``count()``, and ``exists()``
|
||||||
------------------------------------------
|
-----------------------------------------------------------
|
||||||
|
|
||||||
If you are going to need other data from the QuerySet, evaluate it immediately.
|
If you are going to need other data from the QuerySet, evaluate it immediately.
|
||||||
|
|
||||||
For example, assuming an Email model that has a ``subject`` attribute and a
|
For example, assuming a ``Group`` model that has a many-to-many relation to
|
||||||
many-to-many relation to User, the following code is optimal::
|
``User``, the following code is optimal::
|
||||||
|
|
||||||
if display_emails:
|
members = group.members.all()
|
||||||
emails = user.emails.all()
|
|
||||||
if emails:
|
if display_group_members:
|
||||||
print('You have', len(emails), 'emails:')
|
if members:
|
||||||
for email in emails:
|
if current_user in members:
|
||||||
print(email.subject)
|
print("You and", len(members) - 1, "other users are members of this group.")
|
||||||
else:
|
else:
|
||||||
print('You do not have any emails.')
|
print("There are", len(members), "members in this group.")
|
||||||
|
|
||||||
|
for member in members:
|
||||||
|
print(member.username)
|
||||||
|
else:
|
||||||
|
print("There are no members in this group.")
|
||||||
|
|
||||||
It is optimal because:
|
It is optimal because:
|
||||||
|
|
||||||
#. Since QuerySets are lazy, this does no database queries if
|
#. Since QuerySets are lazy, this does no database queries if
|
||||||
``display_emails`` is ``False``.
|
``display_group_members`` is ``False``.
|
||||||
|
|
||||||
#. Storing ``user.emails.all()`` in the ``emails`` variable allows its result
|
#. Storing ``group.members.all()`` in the ``members`` variable allows its
|
||||||
cache to be re-used.
|
result cache to be re-used.
|
||||||
|
|
||||||
#. The line ``if emails`` causes ``QuerySet.__bool__()`` to be called, which
|
#. The line ``if members:`` causes ``QuerySet.__bool__()`` to be called, which
|
||||||
causes the ``user.emails.all()`` query to be run on the database. If there
|
causes the ``group.members.all()`` query to be run on the database. If there
|
||||||
aren't any results, it will return ``False``, otherwise ``True``.
|
aren't any results, it will return ``False``, otherwise ``True``.
|
||||||
|
|
||||||
#. The use of ``len(emails)`` calls ``QuerySet.__len__()``, reusing the result
|
#. The line ``if current_user in members:`` checks if the user is in the result
|
||||||
cache.
|
cache, so no additional database queries are issued.
|
||||||
|
|
||||||
#. The ``for`` loop iterates over the already filled cache.
|
#. The use of ``len(members)`` calls ``QuerySet.__len__()``, reusing the result
|
||||||
|
cache, so again, no database queries are issued.
|
||||||
|
|
||||||
|
#. The ``for member`` loop iterates over the result cache.
|
||||||
|
|
||||||
In total, this code does either one or zero database queries. The only
|
In total, this code does either one or zero database queries. The only
|
||||||
deliberate optimization performed is using the ``emails`` variable. Using
|
deliberate optimization performed is using the ``members`` variable. Using
|
||||||
``QuerySet.exists()`` for the ``if`` or ``QuerySet.count()`` for the count
|
``QuerySet.exists()`` for the ``if``, ``QuerySet.contains()`` for the ``in``,
|
||||||
would each cause additional queries.
|
or ``QuerySet.count()`` for the count would each cause additional queries.
|
||||||
|
|
||||||
Use ``QuerySet.update()`` and ``delete()``
|
Use ``QuerySet.update()`` and ``delete()``
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue