Opened 4 hours ago
Last modified 60 minutes ago
#37218 new Cleanup/optimization
Fetch modes aren't async-compatible — at Version 1
| Reported by: | Jacob Walls | Owned by: | Jacob Walls |
|---|---|---|---|
| Component: | Documentation | Version: | 6.1 |
| Severity: | Normal | Keywords: | fetch modes, async |
| Cc: | Adam Johnson, Simon Charette, Carlton Gibson | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
See fiddle:
from asgiref.sync import async_to_sync from django.contrib.auth.models import User from django.db import models class Person(models.Model): name = models.CharField(max_length=100) user = models.ForeignKey(User, models.CASCADE) @async_to_sync async def async_view(): qs = Person.objects.fetch_mode(models.FETCH_PEERS) async for el in qs: print(el.user) def run(): admin = User.objects.create(username="admin") instance = Person.objects.create(name='John Doe', user=admin) instance2 = Person.objects.create(name='Jane Doe', user=admin) async_view()
File "/app/app/models.py", line 15, in async_view print(el.user) ^^^^^^^ File "/django-pr/django/db/models/fields/related_descriptors.py", line 266, in __get__ instance._state.fetch_mode.fetch(self, instance) File "/django-pr/django/db/models/fetch_modes.py", line 38, in fetch fetcher.fetch_many(instances) File "/django-pr/django/db/models/fields/related_descriptors.py", line 291, in fetch_many prefetch_related_objects(missing_instances, self.field.name) File "/django-pr/django/db/models/query.py", line 2701, in prefetch_related_objects obj_list, additional_lookups = prefetch_one_level( ^^^^^^^^^^^^^^^^^^^ File "/django-pr/django/db/models/query.py", line 2876, in prefetch_one_level all_related_objects = list(rel_qs) ^^^^^^^^^^^^ File "/django-pr/django/db/models/query.py", line 434, in __iter__ self._fetch_all() File "/django-pr/django/db/models/query.py", line 2239, in _fetch_all self._result_cache = list(self._iterable_class(self)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/django-pr/django/db/models/query.py", line 98, in __iter__ results = compiler.execute_sql( ^^^^^^^^^^^^^^^^^^^^^ File "/django-pr/django/db/models/sql/compiler.py", line 1622, in execute_sql cursor = self.connection.cursor() ^^^^^^^^^^^^^^^^^^^^^^^^ File "/django-pr/django/utils/asyncio.py", line 24, in inner raise SynchronousOnlyOperation(message) django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
We probably need to add AFETCH_PEERS and AFETCH_ONE fetch modes, and duplicate the fetch_{one,many}() methods into afetch_{one,many}() on the descriptors.
I can hustle this in before the release candidate if it seems sane.
Change History (1)
comment:1 by , 4 hours ago
| Description: | modified (diff) |
|---|---|
| Severity: | Normal → Release blocker |
Note:
See TracTickets
for help on using tickets.