#30473: len() and count() yield different results on randomly ordered QuerySet 
with
annotation
-------------------------------------+-------------------------------------
               Reporter:  Tobias     |          Owner:  nobody
  Kunze                              |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  2.2
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 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

 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/30473>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/047.77a6bf9cb3f8a634b464d0b03ed8dd58%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to