﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
33835	Select_related().only() in the Prefetch() should automatically add primary keys for reverse relations.	Ipakeev	nobody	"I'm trying to optimize graphQL queries. When I use Prefetch with **select_related** and **only** optimizations, I encounter an increase in database queries. This is because I'm prefetching Book via InverseManyToOne relation and It needs a **publisher_id** in the **only** method.
{{{
class Author(models.Model):
    name = models.CharField(max_length=32)


class Book(models.Model):
    title = models.CharField(max_length=32)
    author = models.ForeignKey(""Author"", on_delete=models.CASCADE)
    publisher = models.ForeignKey(
        ""Publisher"",
        on_delete=models.CASCADE,
        related_name=""books"",
    )


class Publisher(models.Model):
    address = models.CharField(max_length=32)


class AuthorType(DjangoObjectType):
    class Meta:
        model = Author


class BookType(DjangoObjectType):
    class Meta:
        model = Book


class PublisherType(DjangoObjectType):
    class Meta:
        model = Publisher
}}}


Fill in the database:
{{{
        with transaction.atomic():
            authors = Author.objects.bulk_create([
                Author(name=f""Name{i}"") for i in range(10)
            ])
            publishers = Publisher.objects.bulk_create([
                Publisher(address=f""Address{i}"") for i in range(10)
            ])
            Book.objects.bulk_create([
                Book(
                    title=f""Title{i}"",
                    author=random.choice(authors),
                    publisher=random.choice(publishers),
                ) for i in range(20)
            ])
}}}


GraphQL query:
{{{
{
  publishers {
    address
    books {
      title
      author {
        name
      }
    }
  }
}
}}}


22 db queries:
{{{
class Query(graphene.ObjectType):
    publishers = graphene.List(PublisherType)

    def resolve_publishers(self, info):
        queryset = Book.objects.select_related(""author"").only(""title"", ""author__name"")
        return Publisher.objects.prefetch_related(Prefetch(""books"", queryset)).only(""address"")
}}}

2 db queries:
{{{
class Query(graphene.ObjectType):
    publishers = graphene.List(PublisherType)

    def resolve_publishers(self, info):
        queryset = Book.objects.select_related(""author"").only(""title"", ""author__name"", ""publisher_id"")
        return Publisher.objects.prefetch_related(Prefetch(""books"", queryset)).only(""address"")
}}}

I fixed function **prefetch_related_objects** at django/db/models/query.py and now I don't need **publisher_id** in **only** method:
{{{
...
prefetcher, descriptor, attr_found, is_fetched = get_prefetcher(
    first_obj, through_attr, to_attr
)

from django.db.models.fields.related_descriptors import ReverseManyToOneDescriptor
if type(descriptor) is ReverseManyToOneDescriptor:
    lookup.queryset.query.deferred_loading[0].add(descriptor.field.attname)

if not attr_found:
    raise AttributeError(
...
}}}
"	New feature	closed	Database layer (models, ORM)	dev	Normal	wontfix		Simon Charette	Unreviewed	0	0	0	0	0	0
