Loading tests/regressiontests/aggregation_regress/models.py +18 −0 Original line number Diff line number Diff line # coding: utf-8 from django.contrib.contenttypes import generic from django.contrib.contenttypes.models import ContentType from django.db import models from django.utils.encoding import python_2_unicode_compatible Loading @@ -22,6 +24,13 @@ class Publisher(models.Model): return self.name class TaggedItem(models.Model): tag = models.CharField(max_length=100) content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() content_object = generic.GenericForeignKey('content_type', 'object_id') @python_2_unicode_compatible class Book(models.Model): isbn = models.CharField(max_length=9) Loading @@ -33,6 +42,7 @@ class Book(models.Model): contact = models.ForeignKey(Author, related_name='book_contact_set') publisher = models.ForeignKey(Publisher) pubdate = models.DateField() tags = generic.GenericRelation(TaggedItem) class Meta: ordering = ('name',) Loading Loading @@ -63,6 +73,14 @@ class Clues(models.Model): Clue = models.CharField(max_length=150) class WithManualPK(models.Model): # The generic relations regression test needs two different model # classes with the same PK value, and there are some (external) # DB backends that don't work nicely when assigning integer to AutoField # column (MSSQL at least). id = models.IntegerField(primary_key=True) @python_2_unicode_compatible class HardbackBook(Book): weight = models.FloatField() Loading tests/regressiontests/aggregation_regress/tests.py +39 −1 Original line number Diff line number Diff line Loading @@ -6,11 +6,13 @@ from decimal import Decimal from operator import attrgetter from django.core.exceptions import FieldError from django.contrib.contenttypes.models import ContentType from django.db.models import Count, Max, Avg, Sum, StdDev, Variance, F, Q from django.test import TestCase, Approximate, skipUnlessDBFeature from django.utils import six from .models import Author, Book, Publisher, Clues, Entries, HardbackBook from .models import (Author, Book, Publisher, Clues, Entries, HardbackBook, TaggedItem, WithManualPK) class AggregationTests(TestCase): Loading Loading @@ -982,3 +984,39 @@ class AggregationTests(TestCase): def test_reverse_join_trimming(self): qs = Author.objects.annotate(Count('book_contact_set__contact')) self.assertIn(' JOIN ', str(qs.query)) def test_aggregation_with_generic_reverse_relation(self): """ Regression test for #10870: Aggregates with joins ignore extra filters provided by setup_joins tests aggregations with generic reverse relations """ b = Book.objects.get(name='Practical Django Projects') TaggedItem.objects.create(object_id=b.id, tag='intermediate', content_type=ContentType.objects.get_for_model(b)) TaggedItem.objects.create(object_id=b.id, tag='django', content_type=ContentType.objects.get_for_model(b)) # Assign a tag to model with same PK as the book above. If the JOIN # used in aggregation doesn't have content type as part of the # condition the annotation will also count the 'hi mom' tag for b. wmpk = WithManualPK.objects.create(id=b.pk) TaggedItem.objects.create(object_id=wmpk.id, tag='hi mom', content_type=ContentType.objects.get_for_model(wmpk)) b = Book.objects.get(name__startswith='Paradigms of Artificial Intelligence') TaggedItem.objects.create(object_id=b.id, tag='intermediate', content_type=ContentType.objects.get_for_model(b)) self.assertEqual(Book.objects.aggregate(Count('tags')), {'tags__count': 3}) results = Book.objects.annotate(Count('tags')).order_by('-tags__count', 'name') self.assertEqual( [(b.name, b.tags__count) for b in results], [ ('Practical Django Projects', 2), ('Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp', 1), ('Artificial Intelligence: A Modern Approach', 0), ('Python Web Development with Django', 0), ('Sams Teach Yourself Django in 24 Hours', 0), ('The Definitive Guide to Django: Web Development Done Right', 0) ] ) Loading
tests/regressiontests/aggregation_regress/models.py +18 −0 Original line number Diff line number Diff line # coding: utf-8 from django.contrib.contenttypes import generic from django.contrib.contenttypes.models import ContentType from django.db import models from django.utils.encoding import python_2_unicode_compatible Loading @@ -22,6 +24,13 @@ class Publisher(models.Model): return self.name class TaggedItem(models.Model): tag = models.CharField(max_length=100) content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() content_object = generic.GenericForeignKey('content_type', 'object_id') @python_2_unicode_compatible class Book(models.Model): isbn = models.CharField(max_length=9) Loading @@ -33,6 +42,7 @@ class Book(models.Model): contact = models.ForeignKey(Author, related_name='book_contact_set') publisher = models.ForeignKey(Publisher) pubdate = models.DateField() tags = generic.GenericRelation(TaggedItem) class Meta: ordering = ('name',) Loading Loading @@ -63,6 +73,14 @@ class Clues(models.Model): Clue = models.CharField(max_length=150) class WithManualPK(models.Model): # The generic relations regression test needs two different model # classes with the same PK value, and there are some (external) # DB backends that don't work nicely when assigning integer to AutoField # column (MSSQL at least). id = models.IntegerField(primary_key=True) @python_2_unicode_compatible class HardbackBook(Book): weight = models.FloatField() Loading
tests/regressiontests/aggregation_regress/tests.py +39 −1 Original line number Diff line number Diff line Loading @@ -6,11 +6,13 @@ from decimal import Decimal from operator import attrgetter from django.core.exceptions import FieldError from django.contrib.contenttypes.models import ContentType from django.db.models import Count, Max, Avg, Sum, StdDev, Variance, F, Q from django.test import TestCase, Approximate, skipUnlessDBFeature from django.utils import six from .models import Author, Book, Publisher, Clues, Entries, HardbackBook from .models import (Author, Book, Publisher, Clues, Entries, HardbackBook, TaggedItem, WithManualPK) class AggregationTests(TestCase): Loading Loading @@ -982,3 +984,39 @@ class AggregationTests(TestCase): def test_reverse_join_trimming(self): qs = Author.objects.annotate(Count('book_contact_set__contact')) self.assertIn(' JOIN ', str(qs.query)) def test_aggregation_with_generic_reverse_relation(self): """ Regression test for #10870: Aggregates with joins ignore extra filters provided by setup_joins tests aggregations with generic reverse relations """ b = Book.objects.get(name='Practical Django Projects') TaggedItem.objects.create(object_id=b.id, tag='intermediate', content_type=ContentType.objects.get_for_model(b)) TaggedItem.objects.create(object_id=b.id, tag='django', content_type=ContentType.objects.get_for_model(b)) # Assign a tag to model with same PK as the book above. If the JOIN # used in aggregation doesn't have content type as part of the # condition the annotation will also count the 'hi mom' tag for b. wmpk = WithManualPK.objects.create(id=b.pk) TaggedItem.objects.create(object_id=wmpk.id, tag='hi mom', content_type=ContentType.objects.get_for_model(wmpk)) b = Book.objects.get(name__startswith='Paradigms of Artificial Intelligence') TaggedItem.objects.create(object_id=b.id, tag='intermediate', content_type=ContentType.objects.get_for_model(b)) self.assertEqual(Book.objects.aggregate(Count('tags')), {'tags__count': 3}) results = Book.objects.annotate(Count('tags')).order_by('-tags__count', 'name') self.assertEqual( [(b.name, b.tags__count) for b in results], [ ('Practical Django Projects', 2), ('Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp', 1), ('Artificial Intelligence: A Modern Approach', 0), ('Python Web Development with Django', 0), ('Sams Teach Yourself Django in 24 Hours', 0), ('The Definitive Guide to Django: Web Development Done Right', 0) ] )