Opened 51 minutes ago
Last modified 37 minutes ago
#37267 new Bug
Prefetch can populate a reverse foreign key cache with instances of an unrelated queryset model
| Reported by: | beingfaisal | Owned by: | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Normal | Keywords: | Prefetch prefetch_related queryset model |
| Cc: | beingfaisal | Triage Stage: | Unreviewed |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Prefetch() accepts a custom queryset whose model is unrelated to the
model represented by a reverse foreign key lookup. If both models contain
a foreign key with the same name, Django can populate the relationship
cache with instances of the wrong model.
For example:
class Patient(models.Model): pass class ChatAlert(models.Model): patient = models.ForeignKey( Patient, related_name="chatalerts", on_delete=models.CASCADE, ) class HealthAlert(models.Model): patient = models.ForeignKey( Patient, related_name="healthalerts", on_delete=models.CASCADE, )
The following prefetch is accepted:
patient = Patient.objects.create() health_alert = HealthAlert.objects.create(patient=patient) patient = Patient.objects.prefetch_related( Prefetch( "chatalerts", queryset=HealthAlert.objects.all(), ) ).get(pk=patient.pk) alerts = list(patient.chatalerts.all())
Patient.chatalerts represents the reverse side of
ChatAlert.patient, so it should only contain ChatAlert instances.
Instead, alerts contains the HealthAlert instance.
Both models expose patient and patient_id, so the reverse foreign key
prefetch machinery can filter and group the incompatible queryset without
raising an error. With a different schema, the same invalid configuration
may instead fail later with a less clear field or attribute error.
I expect evaluating the prefetch to raise ValueError when the custom
queryset model is incompatible with the relationship model.
A regression test using existing prefetch_related test models fails with:
AssertionError: ValueError not raised
Custom querysets using subclasses of the expected relationship model must
remain supported, as established by #36432. Therefore, compatibility should
be directional: the supplied queryset model may be the expected model or
one of its subclasses, but not an unrelated model.
AI assistance: OpenAI Codex (GPT-5) helped analyze and draft this report.
I manually verified the reproduction.
For completeness, the issue can be reproduced using models already present
in Django's test suite. The following test can be added to
PrefetchRelatedTestsintests/prefetch_related/tests.py:Author.addressesrepresents the reverse side ofAuthorAddress.author, so it expectsAuthorAddressinstances. Thecustom queryset instead returns unrelated
FavoriteAuthorsinstances.Both models expose
authorandauthor_id, so currentmainevaluatesthe prefetch without raising an exception. The test therefore fails with: