﻿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
37427	GenericRelation querysets fail as subqueries after implicit database routing	Lev Zlobin	Lev Zlobin	"Generic relation managers eagerly bind the database selected by the read router, even when the caller hasn't selected a database explicitly. When such a queryset is used in an __in subquery on another connection, this implicit selection triggers the cross-database ValueError.

Ordinary related managers pass the related instance as a router hint without binding an implicit database choice.

=== Reproduction ===

Configure two databases, default and other, with the application's tables and django.contrib.contenttypes migrated on both. The following deterministic router illustrates the issue in a primary/replica configuration:

{{{#!python
class ReplicaRouter:
    def db_for_read(self, model, instance=None, **hints):
        if instance is not None:
            return instance._state.db or ""other""
        return ""other""

    def db_for_write(self, model, **hints):
        return ""default""


DATABASE_ROUTERS = [ReplicaRouter()]
}}}

Models in an installed application:

{{{#!python
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models


class Review(models.Model):
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey()


class Book(models.Model):
    title = models.CharField(max_length=100)
    reviews = GenericRelation(Review)
}}}

After migrating both databases, run:

{{{#!python
book = Book.objects.create(title=""Example"")
Review.objects.create(content_object=book)

inner = book.reviews.all()
outer = Review.objects.filter(pk__in=inner)

# No using() or db_manager() call was made.
assert inner._db == ""default""
assert outer._db is None
assert outer.db == ""other""

list(outer)
}}}

Actual result:

{{{
ValueError: Subqueries aren't allowed across different databases. Force the inner query to be evaluated using `list(inner_query)`.
}}}

Expected result: the subquery should execute on the outer query's connection (other). Evaluating the inner queryset independently should retain instance-aware routing to default.

=== Proposed fix ===

In GenericRelatedObjectManager._apply_rel_filters(), pass the related instance as a queryset routing hint and call using(self._db) only when the manager has an explicitly selected database, following the existing foreign-key and many-to-many related managers.

Explicit using() and db_manager() selections remain respected, including the existing ValueError when an explicitly selected inner database conflicts with the outer connection.

The patch includes a regression test for implicit subquery execution, standalone routing, and explicit database selections, plus documentation explaining database selection for __in subqueries.

Verified against the main development branch. The selected SQLite suites completed successfully (1,433 tests, including 20 skips and 5 expected failures). Formatting, lint checks, and the Sphinx HTML documentation build also passed.

Patch: https://github.com/django/django/pull/22154
"	Bug	assigned	contrib.contenttypes	dev	Normal		GenericRelation multiple-databases subquery routing replicas		Unreviewed	1	0	0	0	0	0
