~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): Raphaël Hertzog
  • Date: 2014-09-17 14:15:11 UTC
  • mfrom: (1.3.17) (6.2.18 experimental)
  • Revision ID: package-import@ubuntu.com-20140917141511-icneokthe9ww5sk4
Tags: 1.7-2
* Release to unstable.
* Add a migrate-south sample script to help users apply their South
  migrations. Thanks to Brian May.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
from __future__ import absolute_import
 
1
from __future__ import unicode_literals
2
2
 
3
3
import datetime
4
4
from decimal import Decimal
 
5
import re
5
6
 
 
7
from django.db import connection
6
8
from django.db.models import Avg, Sum, Count, Max, Min
7
 
from django.test import TestCase, Approximate
 
9
from django.test import TestCase
 
10
from django.test.utils import Approximate
 
11
from django.test.utils import CaptureQueriesContext
8
12
 
9
13
from .models import Author, Publisher, Book, Store
10
14
 
336
340
            price=Decimal("1000"),
337
341
            publisher=p,
338
342
            contact_id=1,
339
 
            pubdate=datetime.date(2008,12,1)
 
343
            pubdate=datetime.date(2008, 12, 1)
340
344
        )
341
345
        Book.objects.create(
342
346
            name='ExpensiveBook2',
346
350
            price=Decimal("1000"),
347
351
            publisher=p,
348
352
            contact_id=1,
349
 
            pubdate=datetime.date(2008,12,2)
 
353
            pubdate=datetime.date(2008, 12, 2)
350
354
        )
351
355
        Book.objects.create(
352
356
            name='ExpensiveBook3',
356
360
            price=Decimal("35"),
357
361
            publisher=p,
358
362
            contact_id=1,
359
 
            pubdate=datetime.date(2008,12,3)
 
363
            pubdate=datetime.date(2008, 12, 3)
360
364
        )
361
365
 
362
366
        publishers = Publisher.objects.annotate(num_books=Count("book__id")).filter(num_books__gt=1).order_by("pk")
439
443
        vals = Author.objects.filter(pk=1).aggregate(Count("friends__id"))
440
444
        self.assertEqual(vals, {"friends__id__count": 2})
441
445
 
442
 
        books = Book.objects.annotate(num_authors=Count("authors__name")).filter(num_authors__ge=2).order_by("pk")
 
446
        books = Book.objects.annotate(num_authors=Count("authors__name")).filter(num_authors__exact=2).order_by("pk")
443
447
        self.assertQuerysetEqual(
444
448
            books, [
445
449
                "The Definitive Guide to Django: Web Development Done Right",
585
589
                "datetime.date(2008, 1, 1)"
586
590
            ]
587
591
        )
 
592
 
 
593
    def test_values_aggregation(self):
 
594
        # Refs #20782
 
595
        max_rating = Book.objects.values('rating').aggregate(max_rating=Max('rating'))
 
596
        self.assertEqual(max_rating['max_rating'], 5)
 
597
        max_books_per_rating = Book.objects.values('rating').annotate(
 
598
            books_per_rating=Count('id')
 
599
        ).aggregate(Max('books_per_rating'))
 
600
        self.assertEqual(
 
601
            max_books_per_rating,
 
602
            {'books_per_rating__max': 3})
 
603
 
 
604
    def test_ticket17424(self):
 
605
        """
 
606
        Check that doing exclude() on a foreign model after annotate()
 
607
        doesn't crash.
 
608
        """
 
609
        all_books = list(Book.objects.values_list('pk', flat=True).order_by('pk'))
 
610
        annotated_books = Book.objects.order_by('pk').annotate(one=Count("id"))
 
611
 
 
612
        # The value doesn't matter, we just need any negative
 
613
        # constraint on a related model that's a noop.
 
614
        excluded_books = annotated_books.exclude(publisher__name="__UNLIKELY_VALUE__")
 
615
 
 
616
        # Try to generate query tree
 
617
        str(excluded_books.query)
 
618
 
 
619
        self.assertQuerysetEqual(excluded_books, all_books, lambda x: x.pk)
 
620
 
 
621
        # Check internal state
 
622
        self.assertIsNone(annotated_books.query.alias_map["aggregation_book"].join_type)
 
623
        self.assertIsNone(excluded_books.query.alias_map["aggregation_book"].join_type)
 
624
 
 
625
    def test_ticket12886(self):
 
626
        """
 
627
        Check that aggregation over sliced queryset works correctly.
 
628
        """
 
629
        qs = Book.objects.all().order_by('-rating')[0:3]
 
630
        vals = qs.aggregate(average_top3_rating=Avg('rating'))['average_top3_rating']
 
631
        self.assertAlmostEqual(vals, 4.5, places=2)
 
632
 
 
633
    def test_ticket11881(self):
 
634
        """
 
635
        Check that subqueries do not needlessly contain ORDER BY, SELECT FOR UPDATE
 
636
        or select_related() stuff.
 
637
        """
 
638
        qs = Book.objects.all().select_for_update().order_by(
 
639
            'pk').select_related('publisher').annotate(max_pk=Max('pk'))
 
640
        with CaptureQueriesContext(connection) as captured_queries:
 
641
            qs.aggregate(avg_pk=Avg('max_pk'))
 
642
            self.assertEqual(len(captured_queries), 1)
 
643
            qstr = captured_queries[0]['sql'].lower()
 
644
            self.assertNotIn('for update', qstr)
 
645
            forced_ordering = connection.ops.force_no_ordering()
 
646
            if forced_ordering:
 
647
                # If the backend needs to force an ordering we make sure it's
 
648
                # the only "ORDER BY" clause present in the query.
 
649
                self.assertEqual(
 
650
                    re.findall(r'order by (\w+)', qstr),
 
651
                    [', '.join(forced_ordering).lower()]
 
652
                )
 
653
            else:
 
654
                self.assertNotIn('order by', qstr)
 
655
            self.assertEqual(qstr.count(' join '), 0)