Code

Ticket #10870: aggregation-generic.4.diff

File aggregation-generic.4.diff, 5.2 KB (added by Alex, 5 years ago)
Line 
1diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
2index f4bf8b2..76d8496 100644
3--- a/django/db/models/sql/query.py
4+++ b/django/db/models/sql/query.py
5@@ -1431,7 +1431,7 @@ 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 
13             # Process the join chain to see if it can be trimmed
14@@ -1444,6 +1444,9 @@ class BaseQuery(object):
15                 self.promote_alias(column_alias, unconditional=True)
16 
17             col = (join_list[-1], col)
18+            for filter in extra:
19+                self.add_filter(filter, can_reuse=set(join_list),
20+                    process_extras=False)
21         else:
22             # The simplest cases. No joins required -
23             # just reference the provided column alias.
24diff --git a/tests/regressiontests/aggregation_regress/models.py b/tests/regressiontests/aggregation_regress/models.py
25index d1f1451..a8b09a8 100644
26--- a/tests/regressiontests/aggregation_regress/models.py
27+++ b/tests/regressiontests/aggregation_regress/models.py
28@@ -3,6 +3,8 @@ import pickle
29 
30 from django.db import models
31 from django.conf import settings
32+from django.contrib.contenttypes import generic
33+from django.contrib.contenttypes.models import ContentType
34 
35 try:
36     sorted
37@@ -34,6 +36,7 @@ class Book(models.Model):
38     contact = models.ForeignKey(Author, related_name='book_contact_set')
39     publisher = models.ForeignKey(Publisher)
40     pubdate = models.DateField()
41+    tags = generic.GenericRelation('TaggedItem')
42 
43     class Meta:
44         ordering = ('name',)
45@@ -66,6 +69,16 @@ class HardbackBook(Book):
46     def __unicode__(self):
47         return "%s (hardback): %s" % (self.name, self.weight)
48 
49+class TaggedItem(models.Model):
50+    tag = models.CharField(max_length=100)
51+    content_type = models.ForeignKey(ContentType, related_name="aggregation_tagged_item_set")
52+    object_id = models.PositiveIntegerField()
53+    content_object = generic.GenericForeignKey('content_type', 'object_id')
54+
55+    def __unicode__(self):
56+        return "%s tagged with %s" % (self.content_object, self.tag)
57+
58+
59 __test__ = {'API_TESTS': """
60 >>> from django.core import management
61 >>> from django.db.models import get_app, F
62@@ -145,17 +158,17 @@ __test__ = {'API_TESTS': """
63 >>> Book.objects.all().aggregate(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('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
73+FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, tags
74 
75 >>> Book.objects.all().annotate(num_authors=Count('authors__id')).aggregate(Max('foo'))
76 Traceback (most recent call last):
77 ...
78-FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, num_authors
79+FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, tags, num_authors
80 
81 # Old-style count aggregations can be mixed with new-style
82 >>> Book.objects.annotate(num_authors=Count('authors')).count()
83@@ -317,7 +330,22 @@ True
84 Traceback (most recent call last):
85 ...
86 FieldError: Cannot compute Avg('mean_age'): 'mean_age' is an aggregate
87-
88+>>> b = Book.objects.get(name='Practical Django Projects')
89+>>> _ = TaggedItem.objects.create(object_id=b.id, content_type=ContentType.objects.get_for_model(b), tag='intermediate')
90+>>> _ = TaggedItem.objects.create(object_id=b.id, content_type=ContentType.objects.get_for_model(b), tag='django')
91+>>> b = Book.objects.get(name__startswith='Paradigms of Artificial Intelligence')
92+>>> _ = TaggedItem.objects.create(object_id=b.id, content_type=ContentType.objects.get_for_model(b), tag='intermediate')
93+
94+>>> s = Store.objects.get(name__startswith='Amazon')
95+>>> _ = TaggedItem.objects.create(object_id=s.id, content_type=ContentType.objects.get_for_model(s), tag='online')
96+>>> Book.objects.aggregate(Count('tags'))
97+{'tags__count': 3}
98+
99+>>> [(b.name, b.tags__count) for b in Book.objects.annotate(Count('tags')).order_by('-tags__count')[:2]]
100+[(u'Practical Django Projects', 2), (u'Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp', 1)]
101+>>> list(Book.objects.annotate(Count('tags')).order_by('name')) == list(Book.objects.order_by('name'))
102+True
103+>>> print Book.objects.annotate(Count('tags')).order_by('name').query
104 """
105 }
106