#37402 assigned Bug

AttributeError when calling first()/last() on an unordered queryset performing aggregation and grouping by an annotation

Reported by: Jacob Walls Owned by: Django Sprints
Component: Database layer (models, ORM) Version: 5.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

02eed4f37879b2077496f86bb1378a076b981233 (#36648) assumed all members of a GROUP BY were Cols. That introduced an AttributeError for cases involving a function output like Lower, shown here:

from django.db import models
from django.db.models.functions import Lower

class Person(models.Model):
    name = models.CharField(max_length=100)

def run():
    # Should raise informative TypeError:
    # Cannot use QuerySet.first() on an unordered queryset performing aggregation.
    # Add an ordering with order_by().
    first = (
        Person.objects
        .values("name")
        .annotate(lower=Lower("name"), count=models.Count("id"))
        .first()
    )
  File "/usr/local/lib/python3.12/site-packages/django/db/models/query.py", line 1187, in first
    self._check_ordering_first_last_queryset_aggregation(method="first")
  File "/usr/local/lib/python3.12/site-packages/django/db/models/query.py", line 2330, in _check_ordering_first_last_queryset_aggregation
    {col.target for col in self.query.group_by}
     ^^^^^^^^^^
AttributeError: 'Ref' object has no attribute 'target'

It's introduced in 5.2, but we could consider backporting to 6.1 as a "crashing bug".

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top