#36135 closed Bug (fixed)
Prefetching a reverse GenericRelation raises AttributeError
Reported by: | john | Owned by: | Simon Charette |
---|---|---|---|
Component: | contrib.contenttypes | Version: | 5.1 |
Severity: | Normal | Keywords: | prefetch |
Cc: | john | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I have some models in my app:
class User(models.Model): name = models.CharField() class Project(models.Model): name = models.CharField() users = models.ManyToManyField('User', related_name='projects') class Task(models.Model): name = models.CharField() project = models.ForeignKey('Project', on_delete=models.DO_NOTHING, related_name='tasks', null=True) link_entity_type = models.ForeignKey(ContentType, on_delete=models.DO_NOTHING, null=True, related_name='link_tasks') link_entity_id = models.IntegerField(null=True) link = GenericForeignKey('link_entity_type', 'link_entity_id') class Version(models.Model): name = models.CharField() task = models.ForeignKey('Task', on_delete=models.DO_NOTHING, related_name='versions', null=True) class Shot(models.Model): name = models.CharField() users = models.ManyToManyField('User', related_name='shots') link_tasks = GenericRelation( 'Task', object_id_field='link_entity_id', content_type_field='link_entity_type'.format(field.name), related_query_name='link_Shot' ) class Asset(models.Model): name = models.CharField() users = models.ManyToManyField('User', related_name='assets') link_tasks = GenericRelation( 'Task', object_id_field='link_entity_id', content_type_field='link_entity_type'.format(field.name), related_query_name='link_Asset' )
If I query Task and prefetch project and users, I will use:
query = Task.objects.all().prefetch_related('project__users') for i in query: print(i.id)
This is ok, I can get the result.
But if I want to query Task and prefetch link_Shot and users
query = Task.objects.all().prefetch_related('link_Shot__users') for i in query: print(i.id)
or
query = Version.objects.all().prefetch_related('task__link_Shot__users') for i in query: print(i.id)
I got error:
Traceback (most recent call last): File "/ela/workspace/xinghuan/issues/sins/sins2server/tmp/tst_query.py", line 35, in <module> for i in query: File "/UNC/fs_user_ws.ela.com/ela/workspace/xinghuan/issues/sins/sins2server/tmp/django/db/models/query.py", line 398, in __iter__ self._fetch_all() File "/UNC/fs_user_ws.ela.com/ela/workspace/xinghuan/issues/sins/sins2server/tmp/django/db/models/query.py", line 1883, in _fetch_all self._prefetch_related_objects() File "/UNC/fs_user_ws.ela.com/ela/workspace/xinghuan/issues/sins/sins2server/tmp/django/db/models/query.py", line 1273, in _prefetch_related_objects prefetch_related_objects(self._result_cache, *self._prefetch_related_lookups) File "/UNC/fs_user_ws.ela.com/ela/workspace/xinghuan/issues/sins/sins2server/tmp/django/db/models/query.py", line 2321, in prefetch_related_objects obj_list, additional_lookups = prefetch_one_level( File "/UNC/fs_user_ws.ela.com/ela/workspace/xinghuan/issues/sins/sins2server/tmp/django/db/models/query.py", line 2463, in prefetch_one_level ) = prefetcher.get_prefetch_queryset(instances, lookup.get_current_queryset(level)) File "/UNC/fs_user_ws.ela.com/ela/workspace/xinghuan/issues/sins/sins2server/tmp/django/db/models/fields/related_descriptors.py", line 746, in get_prefetch_queryset instance = instances_dict[rel_obj_attr(rel_obj)] File "/UNC/fs_user_ws.ela.com/ela/workspace/xinghuan/issues/sins/sins2server/tmp/django/db/models/fields/related.py", line 750, in get_local_related_value return self.get_instance_value_for_fields(instance, self.local_related_fields) File "/UNC/fs_user_ws.ela.com/ela/workspace/xinghuan/issues/sins/sins2server/tmp/django/db/models/fields/related.py", line 772, in get_instance_value_for_fields ret.append(getattr(instance, field.attname)) AttributeError: 'Shot' object has no attribute 'link_entity_id'
The discussion link:
https://forum.djangoproject.com/t/how-to-prefetch-a-genericforeignkey-with-manytomany-field/38168
I'm using Django 4.2.16 and python 3.9.
I also tried Django 5.1.5 and python 3.10 and the error is same.
Change History (8)
comment:1 by , 4 weeks ago
Component: | Uncategorized → contrib.contenttypes |
---|---|
Summary: | Prefetch GenericForeignKey with ManyToMany field error → Prefetching a GenericRelation raises AttributeError |
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 4 weeks ago
Summary: | Prefetching a GenericRelation raises AttributeError → Prefetching a reverse GenericRelation raises AttributeError |
---|
Changing the title as direct GenericRelation
fetching works but their reverse, as defined by related_query_name
, doesn't.
comment:3 by , 4 weeks ago
Has patch: | set |
---|---|
Owner: | set to |
Status: | new → assigned |
comment:4 by , 3 weeks ago
Needs tests: | set |
---|
comment:5 by , 3 weeks ago
Needs tests: | unset |
---|
comment:6 by , 3 weeks ago
Triage Stage: | Accepted → Ready for checkin |
---|
Thank you for the report!
Replicated with Simon's test case in the forum, which raises:
AttributeError: 'Bookmark' object has no attribute 'favorite_fkey'. Did you mean: 'favorite_tags'?
tests/prefetch_related/tests.py