diff --git a/strawberry_django/fields/field.py b/strawberry_django/fields/field.py index fd1caa79..f873c143 100644 --- a/strawberry_django/fields/field.py +++ b/strawberry_django/fields/field.py @@ -183,7 +183,24 @@ def get_result( result = getattr(source, attr.field.attname) elif isinstance(attr, ForwardManyToOneDescriptor): # This will raise KeyError if it is not cached - result = attr.field.get_cached_value(source) # type: ignore + try: + result = attr.field.get_cached_value(source) # type: ignore + except KeyError: + selected_field = next( + f for f in info.selected_fields if f.name == info.field_name + ) + target_attname = attr.field.target_field.attname + if ( + len(selected_field.selections) == 1 + and selected_field.selections[0].name == target_attname + ): + # If we are only retrieving the referenced `id` of a related foreignkey with no additional columns + # then we can optimize away this retrieval by reusing the existing value from the `source` object. + value = source.__dict__[attr.field.get_attname()] + target_model = attr.field.target_field.model + result = target_model(pk=value) + else: + raise elif isinstance(attr, ReverseOneToOneDescriptor): # This will raise KeyError if it is not cached result = attr.related.get_cached_value(source) diff --git a/strawberry_django/optimizer.py b/strawberry_django/optimizer.py index b4761d35..5036db1a 100644 --- a/strawberry_django/optimizer.py +++ b/strawberry_django/optimizer.py @@ -492,7 +492,6 @@ def _get_model_hints( if isinstance(model_field, (models.ForeignKey, OneToOneRel)): store.only.append(path) - store.select_related.append(path) # If adding a reverse relation, make sure to select its pointer to us, # or else this might causa a refetch from the database @@ -514,7 +513,10 @@ def _get_model_hints( cache=cache, level=level + 1, ) - if f_store is not None: + if f_store is not None and set(f_store.only) != { + model_field.target_field.attname + }: + store.select_related.append(path) cache.setdefault(f_model, []).append((level, f_store)) store |= f_store.with_prefix(path, info=info) elif GenericForeignKey and isinstance(model_field, GenericForeignKey):