Opened 5 years ago
Closed 5 years ago
#30473 closed Bug (duplicate)
len() and count() yield different results on randomly ordered QuerySet with annotation,
Reported by: | Tobias Kunze | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
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
I found myself with a QuerySet that is ordered randomly, and found that qs.count()
and len(qs)
return different results.
Additionally, since len(qs)
sets some kind of result cache, any qs.count()
called after len(qs)
will return the same result as len(qs)
, which is an additional source of inconsistency and confusion. I'd argue that at the very least len(qs)
should not be able to change the output of qs.count()
.
Minimal example here:
from django.db import models class Article(models.Model): title = models.CharField(max_length=20) class Review(models.Model): article = models.ForeignKey(to=Article, on_delete=models.CASCADE)
>>> from django.db import models >>> a = Article.objects.create(title='Article') (0.015) INSERT INTO "bar_article" ("title") VALUES ('Article'); args=['Article'] >>> Review.objects.create(article=a) (0.026) INSERT INTO "bar_review" ("article_id") VALUES (1); args=[1] <Review: Review object (1)> >>> Review.objects.create(article=a) (0.014) INSERT INTO "bar_review" ("article_id") VALUES (1); args=[1] <Review: Review object (2)> >>> result = Article.objects.annotate(review_count=models.Count('review')).order_by('?') >>> result.count() (0.000) SELECT COUNT(*) FROM (SELECT "bar_article"."id" AS Col1, COUNT("bar_review"."id") AS "review_count" FROM "bar_article" LEFT OUTER JOIN "bar_review" ON ("bar_article"."id" = "bar_review"."article_id") GROUP BY "bar_article"."id") subquery; args=() 1 >>> len(result) (0.001) SELECT "bar_article"."id", "bar_article"."title", COUNT("bar_review"."id") AS "review_count" FROM "bar_article" LEFT OUTER JOIN "bar_review" ON ("bar_article"."id" = "bar_review"."article_id") GROUP BY "bar_article"."id", "bar_article"."title", RANDOM() ORDER BY RANDOM() ASC; args=() 2 >>> result.count() 2
Change History (1)
comment:1 by , 5 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
Summary: | len() and count() yield different results on randomly ordered QuerySet with annotation → len() and count() yield different results on randomly ordered QuerySet with annotation, |
Version: | 2.2 → master |
Note:
See TracTickets
for help on using tickets.
Thanks for the report. I would say that this is a duplicate of #26390, because this inconsistent behavior is due to the fact
order_by('?')
breaks queryset aggregations.