Opened 45 minutes ago
#37312 new Bug
QuerySet.in_bulk() drops annotations selected by values() and values_list().
| Reported by: | Yassin Bahri | Owned by: | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 6.1 |
| Severity: | Normal | Keywords: | in_bulk values annotations |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
QuerySet.in_bulk() silently drops annotations selected by .values() or .values_list() when the field used as the dictionary key isn't included in the selected fields.
This is reproducible on current main at 5babd2e21ac0877d66c5452da17b97608b337fba and on stable/6.1.x at 4b0185a5fb, using SQLite.
Given these models:
class Author(models.Model): name = models.CharField(max_length=100) class Article(models.Model): headline = models.CharField(max_length=100) author = models.ForeignKey(Author, models.CASCADE)
The following reproduces the issue:
from django.db.models import F author = Author.objects.create(name="Author 1") article = Article.objects.create( headline="Article 1", author=author, ) result = ( Article.objects.annotate(author_name=F("author__name")) .values("headline", "author_name") .in_bulk([article.pk]) ) print(result)
The actual result omits the selected annotation:
{ article.pk: { "headline": "Article 1", } }
The expected result is:
{ article.pk: { "headline": "Article 1", "author_name": "Author 1", } }
The same problem occurs with .values_list():
result = ( Article.objects.annotate(author_name=F("author__name")) .values_list("headline", "author_name") .in_bulk([article.pk]) )
The actual value is:
{article.pk: ("Article 1",)}
instead of:
{article.pk: ("Article 1", "Author 1")}
Support for chaining in_bulk() after values() and values_list() was added in #36605 by 1820d35.
When in_bulk() internally adds the missing key field to the projection, it rebuilds the projection from query.values_select. Selected annotations are stored separately and are therefore omitted from the rebuilt projection.