Code

Ticket #10870: aggregation-generic.diff

File aggregation-generic.diff, 4.7 KB (added by Alex, 5 years ago)

I don't think the solution you've suggested works entirely as with this setup it generates incorrect results for me(it returns 9 instead of 3).

Line 
1diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
2index f4bf8b2..04796f2 100644
3--- a/django/db/models/sql/query.py
4+++ b/django/db/models/sql/query.py
5@@ -1431,8 +1431,11 @@ class BaseQuery(object):
6             #   - this is an annotation over a model field
7             # then we need to explore the joins that are required.
8 
9-            field, source, opts, join_list, last, _ = self.setup_joins(
10+            field, source, opts, join_list, last, extra = self.setup_joins(
11                 field_list, opts, self.get_initial_alias(), False)
12+            # add any extra filters that are needed
13+            if extra:
14+                self.add_filter(*extra)
15 
16             # Process the join chain to see if it can be trimmed
17             col, _, join_list = self.trim_joins(source, join_list, last, False)
18diff --git a/tests/regressiontests/aggregation_regress/models.py b/tests/regressiontests/aggregation_regress/models.py
19index d1f1451..e8e47b0 100644
20--- a/tests/regressiontests/aggregation_regress/models.py
21+++ b/tests/regressiontests/aggregation_regress/models.py
22@@ -3,6 +3,8 @@ import pickle
23 
24 from django.db import models
25 from django.conf import settings
26+from django.contrib.contenttypes import generic
27+from django.contrib.contenttypes.models import ContentType
28 
29 try:
30     sorted
31@@ -34,6 +36,7 @@ class Book(models.Model):
32     contact = models.ForeignKey(Author, related_name='book_contact_set')
33     publisher = models.ForeignKey(Publisher)
34     pubdate = models.DateField()
35+    tags = generic.GenericRelation('TaggedItem')
36 
37     class Meta:
38         ordering = ('name',)
39@@ -66,6 +69,16 @@ class HardbackBook(Book):
40     def __unicode__(self):
41         return "%s (hardback): %s" % (self.name, self.weight)
42 
43+class TaggedItem(models.Model):
44+    tag = models.CharField(max_length=100)
45+    content_type = models.ForeignKey(ContentType)
46+    object_id = models.PositiveIntegerField()
47+    content_object = generic.GenericForeignKey('content_type', 'object_id')
48+
49+    def __unicode__(self):
50+        return "%s tagged with %s" % (self.content_object, self.tag)
51+
52+
53 __test__ = {'API_TESTS': """
54 >>> from django.core import management
55 >>> from django.db.models import get_app, F
56@@ -145,17 +158,17 @@ __test__ = {'API_TESTS': """
57 >>> Book.objects.all().aggregate(num_authors=Count('foo'))
58 Traceback (most recent call last):
59 ...
60-FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store
61+FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, tags
62 
63 >>> Book.objects.all().annotate(num_authors=Count('foo'))
64 Traceback (most recent call last):
65 ...
66-FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store
67+FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, tags
68 
69 >>> Book.objects.all().annotate(num_authors=Count('authors__id')).aggregate(Max('foo'))
70 Traceback (most recent call last):
71 ...
72-FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, num_authors
73+FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, tags, num_authors
74 
75 # Old-style count aggregations can be mixed with new-style
76 >>> Book.objects.annotate(num_authors=Count('authors')).count()
77@@ -317,7 +330,21 @@ True
78 Traceback (most recent call last):
79 ...
80 FieldError: Cannot compute Avg('mean_age'): 'mean_age' is an aggregate
81-
82+>>> b = Book.objects.get(name='Practical Django Projects')
83+>>> _ = TaggedItem.objects.create(object_id=b.id, content_type=ContentType.objects.get_for_model(b), tag='intermediate')
84+>>> _ = TaggedItem.objects.create(object_id=b.id, content_type=ContentType.objects.get_for_model(b), tag='django')
85+>>> b = Book.objects.get(name__startswith='Paradigms of Artificial Intelligence')
86+>>> _ = TaggedItem.objects.create(object_id=b.id, content_type=ContentType.objects.get_for_model(b), tag='intermediate')
87+
88+>>> s = Store.objects.get(name__startswith='Amazon')
89+>>> _ = TaggedItem.objects.create(object_id=s.id, content_type=ContentType.objects.get_for_model(s), tag='online')
90+>>> from django.conf import settings
91+>>> settings.DEBUG = True
92+>>> from django.db import connection, reset_queries
93+>>> reset_queries()
94+>>> Book.objects.aggregate(Count('tags'))
95+{'tags__count': 3}
96+>>> connection.queries
97 """
98 }
99