Browse Source

Changed "Don't overuse count() or exists()" example to Python.

Adam Johnson 4 years ago
parent
commit
8a642b88c3
1 changed files with 24 additions and 32 deletions
  1. 24 32
      docs/topics/db/optimization.txt

+ 24 - 32
docs/topics/db/optimization.txt

@@ -260,47 +260,39 @@ Don't overuse ``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 ``body`` attribute and a
-many-to-many relation to User, the following template code is optimal:
-
-.. code-block:: html+django
-
-   {% if display_inbox %}
-     {% with emails=user.emails.all %}
-       {% if emails %}
-         <p>You have {{ emails|length }} email(s)</p>
-         {% for email in emails %}
-           <p>{{ email.body }}</p>
-         {% endfor %}
-       {% else %}
-         <p>No messages today.</p>
-       {% endif %}
-     {% endwith %}
-   {% endif %}
-
+For example, assuming an Email model that has a ``subject`` attribute and a
+many-to-many relation to User, the following code is optimal::
+
+    if display_emails:
+        emails = user.emails.all()
+        if emails:
+            print('You have', len(emails), 'emails:')
+            for email in emails:
+                print(email.subject)
+        else:
+            print('You do not have any emails.')
 
 
 It is optimal because:
 It is optimal because:
 
 
-#. Since QuerySets are lazy, this does no database queries if 'display_inbox'
-   is False.
+#. Since QuerySets are lazy, this does no database queries if
+   ``display_emails`` is ``False``.
 
 
-#. Use of :ttag:`with` means that we store ``user.emails.all`` in a variable
-   for later use, allowing its cache to be re-used.
+#. Storing ``user.emails.all()`` in the ``emails`` variable allows its result
+   cache to be re-used.
 
 
-#. The line ``{% if emails %}`` causes ``QuerySet.__bool__()`` to be called,
-   which causes the ``user.emails.all()`` query to be run on the database, and
-   at the least the first line to be turned into an ORM object. If there aren't
-   any results, it will return False, otherwise True.
+#. The line ``if emails`` causes ``QuerySet.__bool__()`` to be called, which
+   causes the ``user.emails.all()`` query to be run on the database. If there
+   aren't any results, it will return ``False``, otherwise ``True``.
 
 
-#. The use of ``{{ emails|length }}`` calls ``QuerySet.__len__()``, filling
-   out the rest of the cache without doing another query.
+#. The use of ``len(emails)`` calls ``QuerySet.__len__()``, reusing the result
+   cache.
 
 
-#. The :ttag:`for` loop iterates over the already filled cache.
+#. The ``for`` loop iterates over the already filled 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 the use of the :ttag:`with` tag. Using
-``QuerySet.exists()`` or ``QuerySet.count()`` at any point would cause
-additional queries.
+deliberate optimization performed is using the ``emails`` variable. Using
+``QuerySet.exists()`` for the ``if`` or ``QuerySet.count()`` for the count
+would each cause additional queries.
 
 
 Use ``QuerySet.update()`` and ``delete()``
 Use ``QuerySet.update()`` and ``delete()``
 ------------------------------------------
 ------------------------------------------