mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[3.2.x] Changed "Don't overuse count() or exists()" example to Python.
Backport of 8a642b88c3 from master
			
			
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							73e7bfc8f5
						
					
				
				
					commit
					ba71cf38ea
				
			| @@ -260,47 +260,39 @@ Don't overuse ``count()`` and ``exists()`` | ||||
|  | ||||
| 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: | ||||
|  | ||||
| #. 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 | ||||
| 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()`` | ||||
| ------------------------------------------ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user