~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to tests/aggregation/tests.py

  • Committer: Package Import Robot
  • Author(s): Luke Faraone
  • Date: 2013-11-07 15:33:49 UTC
  • mfrom: (1.3.12)
  • Revision ID: package-import@ubuntu.com-20131107153349-e31sc149l2szs3jb
Tags: 1.6-1
* New upstream version. Closes: #557474, #724637.
* python-django now also suggests the installation of ipython,
  bpython, python-django-doc, and libgdal1.
  Closes: #636511, #686333, #704203
* Set package maintainer to Debian Python Modules Team.
* Bump standards version to 3.9.5, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from __future__ import absolute_import
 
2
 
 
3
import datetime
 
4
from decimal import Decimal
 
5
 
 
6
from django.db.models import Avg, Sum, Count, Max, Min
 
7
from django.test import TestCase, Approximate
 
8
 
 
9
from .models import Author, Publisher, Book, Store
 
10
 
 
11
 
 
12
class BaseAggregateTestCase(TestCase):
 
13
    fixtures = ["aggregation.json"]
 
14
 
 
15
    def test_empty_aggregate(self):
 
16
        self.assertEqual(Author.objects.all().aggregate(), {})
 
17
 
 
18
    def test_single_aggregate(self):
 
19
        vals = Author.objects.aggregate(Avg("age"))
 
20
        self.assertEqual(vals, {"age__avg": Approximate(37.4, places=1)})
 
21
 
 
22
    def test_multiple_aggregates(self):
 
23
        vals = Author.objects.aggregate(Sum("age"), Avg("age"))
 
24
        self.assertEqual(vals, {"age__sum": 337, "age__avg": Approximate(37.4, places=1)})
 
25
 
 
26
    def test_filter_aggregate(self):
 
27
        vals = Author.objects.filter(age__gt=29).aggregate(Sum("age"))
 
28
        self.assertEqual(len(vals), 1)
 
29
        self.assertEqual(vals["age__sum"], 254)
 
30
 
 
31
    def test_related_aggregate(self):
 
32
        vals = Author.objects.aggregate(Avg("friends__age"))
 
33
        self.assertEqual(len(vals), 1)
 
34
        self.assertAlmostEqual(vals["friends__age__avg"], 34.07, places=2)
 
35
 
 
36
        vals = Book.objects.filter(rating__lt=4.5).aggregate(Avg("authors__age"))
 
37
        self.assertEqual(len(vals), 1)
 
38
        self.assertAlmostEqual(vals["authors__age__avg"], 38.2857, places=2)
 
39
 
 
40
        vals = Author.objects.all().filter(name__contains="a").aggregate(Avg("book__rating"))
 
41
        self.assertEqual(len(vals), 1)
 
42
        self.assertEqual(vals["book__rating__avg"], 4.0)
 
43
 
 
44
        vals = Book.objects.aggregate(Sum("publisher__num_awards"))
 
45
        self.assertEqual(len(vals), 1)
 
46
        self.assertEqual(vals["publisher__num_awards__sum"], 30)
 
47
 
 
48
        vals = Publisher.objects.aggregate(Sum("book__price"))
 
49
        self.assertEqual(len(vals), 1)
 
50
        self.assertEqual(vals["book__price__sum"], Decimal("270.27"))
 
51
 
 
52
    def test_aggregate_multi_join(self):
 
53
        vals = Store.objects.aggregate(Max("books__authors__age"))
 
54
        self.assertEqual(len(vals), 1)
 
55
        self.assertEqual(vals["books__authors__age__max"], 57)
 
56
 
 
57
        vals = Author.objects.aggregate(Min("book__publisher__num_awards"))
 
58
        self.assertEqual(len(vals), 1)
 
59
        self.assertEqual(vals["book__publisher__num_awards__min"], 1)
 
60
 
 
61
    def test_aggregate_alias(self):
 
62
        vals = Store.objects.filter(name="Amazon.com").aggregate(amazon_mean=Avg("books__rating"))
 
63
        self.assertEqual(len(vals), 1)
 
64
        self.assertAlmostEqual(vals["amazon_mean"], 4.08, places=2)
 
65
 
 
66
    def test_annotate_basic(self):
 
67
        self.assertQuerysetEqual(
 
68
            Book.objects.annotate().order_by('pk'), [
 
69
                "The Definitive Guide to Django: Web Development Done Right",
 
70
                "Sams Teach Yourself Django in 24 Hours",
 
71
                "Practical Django Projects",
 
72
                "Python Web Development with Django",
 
73
                "Artificial Intelligence: A Modern Approach",
 
74
                "Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp"
 
75
            ],
 
76
            lambda b: b.name
 
77
        )
 
78
 
 
79
        books = Book.objects.annotate(mean_age=Avg("authors__age"))
 
80
        b = books.get(pk=1)
 
81
        self.assertEqual(
 
82
            b.name,
 
83
            'The Definitive Guide to Django: Web Development Done Right'
 
84
        )
 
85
        self.assertEqual(b.mean_age, 34.5)
 
86
 
 
87
    def test_annotate_m2m(self):
 
88
        books = Book.objects.filter(rating__lt=4.5).annotate(Avg("authors__age")).order_by("name")
 
89
        self.assertQuerysetEqual(
 
90
            books, [
 
91
                ('Artificial Intelligence: A Modern Approach', 51.5),
 
92
                ('Practical Django Projects', 29.0),
 
93
                ('Python Web Development with Django', Approximate(30.3, places=1)),
 
94
                ('Sams Teach Yourself Django in 24 Hours', 45.0)
 
95
            ],
 
96
            lambda b: (b.name, b.authors__age__avg),
 
97
        )
 
98
 
 
99
        books = Book.objects.annotate(num_authors=Count("authors")).order_by("name")
 
100
        self.assertQuerysetEqual(
 
101
            books, [
 
102
                ('Artificial Intelligence: A Modern Approach', 2),
 
103
                ('Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp', 1),
 
104
                ('Practical Django Projects', 1),
 
105
                ('Python Web Development with Django', 3),
 
106
                ('Sams Teach Yourself Django in 24 Hours', 1),
 
107
                ('The Definitive Guide to Django: Web Development Done Right', 2)
 
108
            ],
 
109
            lambda b: (b.name, b.num_authors)
 
110
        )
 
111
 
 
112
    def test_backwards_m2m_annotate(self):
 
113
        authors = Author.objects.filter(name__contains="a").annotate(Avg("book__rating")).order_by("name")
 
114
        self.assertQuerysetEqual(
 
115
            authors, [
 
116
                ('Adrian Holovaty', 4.5),
 
117
                ('Brad Dayley', 3.0),
 
118
                ('Jacob Kaplan-Moss', 4.5),
 
119
                ('James Bennett', 4.0),
 
120
                ('Paul Bissex', 4.0),
 
121
                ('Stuart Russell', 4.0)
 
122
            ],
 
123
            lambda a: (a.name, a.book__rating__avg)
 
124
        )
 
125
 
 
126
        authors = Author.objects.annotate(num_books=Count("book")).order_by("name")
 
127
        self.assertQuerysetEqual(
 
128
            authors, [
 
129
                ('Adrian Holovaty', 1),
 
130
                ('Brad Dayley', 1),
 
131
                ('Jacob Kaplan-Moss', 1),
 
132
                ('James Bennett', 1),
 
133
                ('Jeffrey Forcier', 1),
 
134
                ('Paul Bissex', 1),
 
135
                ('Peter Norvig', 2),
 
136
                ('Stuart Russell', 1),
 
137
                ('Wesley J. Chun', 1)
 
138
            ],
 
139
            lambda a: (a.name, a.num_books)
 
140
        )
 
141
 
 
142
    def test_reverse_fkey_annotate(self):
 
143
        books = Book.objects.annotate(Sum("publisher__num_awards")).order_by("name")
 
144
        self.assertQuerysetEqual(
 
145
            books, [
 
146
                ('Artificial Intelligence: A Modern Approach', 7),
 
147
                ('Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp', 9),
 
148
                ('Practical Django Projects', 3),
 
149
                ('Python Web Development with Django', 7),
 
150
                ('Sams Teach Yourself Django in 24 Hours', 1),
 
151
                ('The Definitive Guide to Django: Web Development Done Right', 3)
 
152
            ],
 
153
            lambda b: (b.name, b.publisher__num_awards__sum)
 
154
        )
 
155
 
 
156
        publishers = Publisher.objects.annotate(Sum("book__price")).order_by("name")
 
157
        self.assertQuerysetEqual(
 
158
            publishers, [
 
159
                ('Apress', Decimal("59.69")),
 
160
                ("Jonno's House of Books", None),
 
161
                ('Morgan Kaufmann', Decimal("75.00")),
 
162
                ('Prentice Hall', Decimal("112.49")),
 
163
                ('Sams', Decimal("23.09"))
 
164
            ],
 
165
            lambda p: (p.name, p.book__price__sum)
 
166
        )
 
167
 
 
168
    def test_annotate_values(self):
 
169
        books = list(Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values())
 
170
        self.assertEqual(
 
171
            books, [
 
172
                {
 
173
                    "contact_id": 1,
 
174
                    "id": 1,
 
175
                    "isbn": "159059725",
 
176
                    "mean_age": 34.5,
 
177
                    "name": "The Definitive Guide to Django: Web Development Done Right",
 
178
                    "pages": 447,
 
179
                    "price": Approximate(Decimal("30")),
 
180
                    "pubdate": datetime.date(2007, 12, 6),
 
181
                    "publisher_id": 1,
 
182
                    "rating": 4.5,
 
183
                }
 
184
            ]
 
185
        )
 
186
 
 
187
        books = Book.objects.filter(pk=1).annotate(mean_age=Avg('authors__age')).values('pk', 'isbn', 'mean_age')
 
188
        self.assertEqual(
 
189
            list(books), [
 
190
                {
 
191
                    "pk": 1,
 
192
                    "isbn": "159059725",
 
193
                    "mean_age": 34.5,
 
194
                }
 
195
            ]
 
196
        )
 
197
 
 
198
        books = Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values("name")
 
199
        self.assertEqual(
 
200
            list(books), [
 
201
                {
 
202
                    "name": "The Definitive Guide to Django: Web Development Done Right"
 
203
                }
 
204
            ]
 
205
        )
 
206
 
 
207
        books = Book.objects.filter(pk=1).values().annotate(mean_age=Avg('authors__age'))
 
208
        self.assertEqual(
 
209
            list(books), [
 
210
                {
 
211
                    "contact_id": 1,
 
212
                    "id": 1,
 
213
                    "isbn": "159059725",
 
214
                    "mean_age": 34.5,
 
215
                    "name": "The Definitive Guide to Django: Web Development Done Right",
 
216
                    "pages": 447,
 
217
                    "price": Approximate(Decimal("30")),
 
218
                    "pubdate": datetime.date(2007, 12, 6),
 
219
                    "publisher_id": 1,
 
220
                    "rating": 4.5,
 
221
                }
 
222
            ]
 
223
        )
 
224
 
 
225
        books = Book.objects.values("rating").annotate(n_authors=Count("authors__id"), mean_age=Avg("authors__age")).order_by("rating")
 
226
        self.assertEqual(
 
227
            list(books), [
 
228
                {
 
229
                    "rating": 3.0,
 
230
                    "n_authors": 1,
 
231
                    "mean_age": 45.0,
 
232
                },
 
233
                {
 
234
                    "rating": 4.0,
 
235
                    "n_authors": 6,
 
236
                    "mean_age": Approximate(37.16, places=1)
 
237
                },
 
238
                {
 
239
                    "rating": 4.5,
 
240
                    "n_authors": 2,
 
241
                    "mean_age": 34.5,
 
242
                },
 
243
                {
 
244
                    "rating": 5.0,
 
245
                    "n_authors": 1,
 
246
                    "mean_age": 57.0,
 
247
                }
 
248
            ]
 
249
        )
 
250
 
 
251
        authors = Author.objects.annotate(Avg("friends__age")).order_by("name")
 
252
        self.assertEqual(len(authors), 9)
 
253
        self.assertQuerysetEqual(
 
254
            authors, [
 
255
                ('Adrian Holovaty', 32.0),
 
256
                ('Brad Dayley', None),
 
257
                ('Jacob Kaplan-Moss', 29.5),
 
258
                ('James Bennett', 34.0),
 
259
                ('Jeffrey Forcier', 27.0),
 
260
                ('Paul Bissex', 31.0),
 
261
                ('Peter Norvig', 46.0),
 
262
                ('Stuart Russell', 57.0),
 
263
                ('Wesley J. Chun', Approximate(33.66, places=1))
 
264
            ],
 
265
            lambda a: (a.name, a.friends__age__avg)
 
266
        )
 
267
 
 
268
    def test_count(self):
 
269
        vals = Book.objects.aggregate(Count("rating"))
 
270
        self.assertEqual(vals, {"rating__count": 6})
 
271
 
 
272
        vals = Book.objects.aggregate(Count("rating", distinct=True))
 
273
        self.assertEqual(vals, {"rating__count": 4})
 
274
 
 
275
    def test_fkey_aggregate(self):
 
276
        explicit = list(Author.objects.annotate(Count('book__id')))
 
277
        implicit = list(Author.objects.annotate(Count('book')))
 
278
        self.assertEqual(explicit, implicit)
 
279
 
 
280
    def test_annotate_ordering(self):
 
281
        books = Book.objects.values('rating').annotate(oldest=Max('authors__age')).order_by('oldest', 'rating')
 
282
        self.assertEqual(
 
283
            list(books), [
 
284
                {
 
285
                    "rating": 4.5,
 
286
                    "oldest": 35,
 
287
                },
 
288
                {
 
289
                    "rating": 3.0,
 
290
                    "oldest": 45
 
291
                },
 
292
                {
 
293
                    "rating": 4.0,
 
294
                    "oldest": 57,
 
295
                },
 
296
                {
 
297
                    "rating": 5.0,
 
298
                    "oldest": 57,
 
299
                }
 
300
            ]
 
301
        )
 
302
 
 
303
        books = Book.objects.values("rating").annotate(oldest=Max("authors__age")).order_by("-oldest", "-rating")
 
304
        self.assertEqual(
 
305
            list(books), [
 
306
                {
 
307
                    "rating": 5.0,
 
308
                    "oldest": 57,
 
309
                },
 
310
                {
 
311
                    "rating": 4.0,
 
312
                    "oldest": 57,
 
313
                },
 
314
                {
 
315
                    "rating": 3.0,
 
316
                    "oldest": 45,
 
317
                },
 
318
                {
 
319
                    "rating": 4.5,
 
320
                    "oldest": 35,
 
321
                }
 
322
            ]
 
323
        )
 
324
 
 
325
    def test_aggregate_annotation(self):
 
326
        vals = Book.objects.annotate(num_authors=Count("authors__id")).aggregate(Avg("num_authors"))
 
327
        self.assertEqual(vals, {"num_authors__avg": Approximate(1.66, places=1)})
 
328
 
 
329
    def test_filtering(self):
 
330
        p = Publisher.objects.create(name='Expensive Publisher', num_awards=0)
 
331
        Book.objects.create(
 
332
            name='ExpensiveBook1',
 
333
            pages=1,
 
334
            isbn='111',
 
335
            rating=3.5,
 
336
            price=Decimal("1000"),
 
337
            publisher=p,
 
338
            contact_id=1,
 
339
            pubdate=datetime.date(2008,12,1)
 
340
        )
 
341
        Book.objects.create(
 
342
            name='ExpensiveBook2',
 
343
            pages=1,
 
344
            isbn='222',
 
345
            rating=4.0,
 
346
            price=Decimal("1000"),
 
347
            publisher=p,
 
348
            contact_id=1,
 
349
            pubdate=datetime.date(2008,12,2)
 
350
        )
 
351
        Book.objects.create(
 
352
            name='ExpensiveBook3',
 
353
            pages=1,
 
354
            isbn='333',
 
355
            rating=4.5,
 
356
            price=Decimal("35"),
 
357
            publisher=p,
 
358
            contact_id=1,
 
359
            pubdate=datetime.date(2008,12,3)
 
360
        )
 
361
 
 
362
        publishers = Publisher.objects.annotate(num_books=Count("book__id")).filter(num_books__gt=1).order_by("pk")
 
363
        self.assertQuerysetEqual(
 
364
            publishers, [
 
365
                "Apress",
 
366
                "Prentice Hall",
 
367
                "Expensive Publisher",
 
368
            ],
 
369
            lambda p: p.name,
 
370
        )
 
371
 
 
372
        publishers = Publisher.objects.filter(book__price__lt=Decimal("40.0")).order_by("pk")
 
373
        self.assertQuerysetEqual(
 
374
            publishers, [
 
375
                "Apress",
 
376
                "Apress",
 
377
                "Sams",
 
378
                "Prentice Hall",
 
379
                "Expensive Publisher",
 
380
            ],
 
381
            lambda p: p.name
 
382
        )
 
383
 
 
384
        publishers = Publisher.objects.annotate(num_books=Count("book__id")).filter(num_books__gt=1, book__price__lt=Decimal("40.0")).order_by("pk")
 
385
        self.assertQuerysetEqual(
 
386
            publishers, [
 
387
                "Apress",
 
388
                "Prentice Hall",
 
389
                "Expensive Publisher",
 
390
            ],
 
391
            lambda p: p.name,
 
392
        )
 
393
 
 
394
        publishers = Publisher.objects.filter(book__price__lt=Decimal("40.0")).annotate(num_books=Count("book__id")).filter(num_books__gt=1).order_by("pk")
 
395
        self.assertQuerysetEqual(
 
396
            publishers, [
 
397
                "Apress",
 
398
            ],
 
399
            lambda p: p.name
 
400
        )
 
401
 
 
402
        publishers = Publisher.objects.annotate(num_books=Count("book")).filter(num_books__range=[1, 3]).order_by("pk")
 
403
        self.assertQuerysetEqual(
 
404
            publishers, [
 
405
                "Apress",
 
406
                "Sams",
 
407
                "Prentice Hall",
 
408
                "Morgan Kaufmann",
 
409
                "Expensive Publisher",
 
410
            ],
 
411
            lambda p: p.name
 
412
        )
 
413
 
 
414
        publishers = Publisher.objects.annotate(num_books=Count("book")).filter(num_books__range=[1, 2]).order_by("pk")
 
415
        self.assertQuerysetEqual(
 
416
            publishers, [
 
417
                "Apress",
 
418
                "Sams",
 
419
                "Prentice Hall",
 
420
                "Morgan Kaufmann",
 
421
            ],
 
422
            lambda p: p.name
 
423
        )
 
424
 
 
425
        publishers = Publisher.objects.annotate(num_books=Count("book")).filter(num_books__in=[1, 3]).order_by("pk")
 
426
        self.assertQuerysetEqual(
 
427
            publishers, [
 
428
                "Sams",
 
429
                "Morgan Kaufmann",
 
430
                "Expensive Publisher",
 
431
            ],
 
432
            lambda p: p.name,
 
433
        )
 
434
 
 
435
        publishers = Publisher.objects.annotate(num_books=Count("book")).filter(num_books__isnull=True)
 
436
        self.assertEqual(len(publishers), 0)
 
437
 
 
438
    def test_annotation(self):
 
439
        vals = Author.objects.filter(pk=1).aggregate(Count("friends__id"))
 
440
        self.assertEqual(vals, {"friends__id__count": 2})
 
441
 
 
442
        books = Book.objects.annotate(num_authors=Count("authors__name")).filter(num_authors__ge=2).order_by("pk")
 
443
        self.assertQuerysetEqual(
 
444
            books, [
 
445
                "The Definitive Guide to Django: Web Development Done Right",
 
446
                "Artificial Intelligence: A Modern Approach",
 
447
            ],
 
448
            lambda b: b.name
 
449
        )
 
450
 
 
451
        authors = Author.objects.annotate(num_friends=Count("friends__id", distinct=True)).filter(num_friends=0).order_by("pk")
 
452
        self.assertQuerysetEqual(
 
453
            authors, [
 
454
                "Brad Dayley",
 
455
            ],
 
456
            lambda a: a.name
 
457
        )
 
458
 
 
459
        publishers = Publisher.objects.annotate(num_books=Count("book__id")).filter(num_books__gt=1).order_by("pk")
 
460
        self.assertQuerysetEqual(
 
461
            publishers, [
 
462
                "Apress",
 
463
                "Prentice Hall",
 
464
            ],
 
465
            lambda p: p.name
 
466
        )
 
467
 
 
468
        publishers = Publisher.objects.filter(book__price__lt=Decimal("40.0")).annotate(num_books=Count("book__id")).filter(num_books__gt=1)
 
469
        self.assertQuerysetEqual(
 
470
            publishers, [
 
471
                "Apress",
 
472
            ],
 
473
            lambda p: p.name
 
474
        )
 
475
 
 
476
        books = Book.objects.annotate(num_authors=Count("authors__id")).filter(authors__name__contains="Norvig", num_authors__gt=1)
 
477
        self.assertQuerysetEqual(
 
478
            books, [
 
479
                "Artificial Intelligence: A Modern Approach",
 
480
            ],
 
481
            lambda b: b.name
 
482
        )
 
483
 
 
484
    def test_more_aggregation(self):
 
485
        a = Author.objects.get(name__contains='Norvig')
 
486
        b = Book.objects.get(name__contains='Done Right')
 
487
        b.authors.add(a)
 
488
        b.save()
 
489
 
 
490
        vals = Book.objects.annotate(num_authors=Count("authors__id")).filter(authors__name__contains="Norvig", num_authors__gt=1).aggregate(Avg("rating"))
 
491
        self.assertEqual(vals, {"rating__avg": 4.25})
 
492
 
 
493
    def test_even_more_aggregate(self):
 
494
        publishers = Publisher.objects.annotate(earliest_book=Min("book__pubdate")).exclude(earliest_book=None).order_by("earliest_book").values()
 
495
        self.assertEqual(
 
496
            list(publishers), [
 
497
                {
 
498
                    'earliest_book': datetime.date(1991, 10, 15),
 
499
                    'num_awards': 9,
 
500
                    'id': 4,
 
501
                    'name': 'Morgan Kaufmann'
 
502
                },
 
503
                {
 
504
                    'earliest_book': datetime.date(1995, 1, 15),
 
505
                    'num_awards': 7,
 
506
                    'id': 3,
 
507
                    'name': 'Prentice Hall'
 
508
                },
 
509
                {
 
510
                    'earliest_book': datetime.date(2007, 12, 6),
 
511
                    'num_awards': 3,
 
512
                    'id': 1,
 
513
                    'name': 'Apress'
 
514
                },
 
515
                {
 
516
                    'earliest_book': datetime.date(2008, 3, 3),
 
517
                    'num_awards': 1,
 
518
                    'id': 2,
 
519
                    'name': 'Sams'
 
520
                }
 
521
            ]
 
522
        )
 
523
 
 
524
        vals = Store.objects.aggregate(Max("friday_night_closing"), Min("original_opening"))
 
525
        self.assertEqual(
 
526
            vals,
 
527
            {
 
528
                "friday_night_closing__max": datetime.time(23, 59, 59),
 
529
                "original_opening__min": datetime.datetime(1945, 4, 25, 16, 24, 14),
 
530
            }
 
531
        )
 
532
 
 
533
    def test_annotate_values_list(self):
 
534
        books = Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values_list("pk", "isbn", "mean_age")
 
535
        self.assertEqual(
 
536
            list(books), [
 
537
                (1, "159059725", 34.5),
 
538
            ]
 
539
        )
 
540
 
 
541
        books = Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values_list("isbn")
 
542
        self.assertEqual(
 
543
            list(books), [
 
544
                ('159059725',)
 
545
            ]
 
546
        )
 
547
 
 
548
        books = Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values_list("mean_age")
 
549
        self.assertEqual(
 
550
            list(books), [
 
551
                (34.5,)
 
552
            ]
 
553
        )
 
554
 
 
555
        books = Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values_list("mean_age", flat=True)
 
556
        self.assertEqual(list(books), [34.5])
 
557
 
 
558
        books = Book.objects.values_list("price").annotate(count=Count("price")).order_by("-count", "price")
 
559
        self.assertEqual(
 
560
            list(books), [
 
561
                (Decimal("29.69"), 2),
 
562
                (Decimal('23.09'), 1),
 
563
                (Decimal('30'), 1),
 
564
                (Decimal('75'), 1),
 
565
                (Decimal('82.8'), 1),
 
566
            ]
 
567
        )
 
568
 
 
569
    def test_dates_with_aggregation(self):
 
570
        """
 
571
        Test that .dates() returns a distinct set of dates when applied to a
 
572
        QuerySet with aggregation.
 
573
 
 
574
        Refs #18056. Previously, .dates() would return distinct (date_kind,
 
575
        aggregation) sets, in this case (year, num_authors), so 2008 would be
 
576
        returned twice because there are books from 2008 with a different
 
577
        number of authors.
 
578
        """
 
579
        dates = Book.objects.annotate(num_authors=Count("authors")).dates('pubdate', 'year')
 
580
        self.assertQuerysetEqual(
 
581
            dates, [
 
582
                "datetime.date(1991, 1, 1)",
 
583
                "datetime.date(1995, 1, 1)",
 
584
                "datetime.date(2007, 1, 1)",
 
585
                "datetime.date(2008, 1, 1)"
 
586
            ]
 
587
        )