Ticket #10870: aggregation-generic.diff

File aggregation-generic.diff, 4.7 KB (added by Alex, 6 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).

  • django/db/models/sql/query.py

    diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
    index f4bf8b2..04796f2 100644
    a b class BaseQuery(object): 
    14311431            #   - this is an annotation over a model field
    14321432            # then we need to explore the joins that are required.
    14331433
    1434             field, source, opts, join_list, last, _ = self.setup_joins(
     1434            field, source, opts, join_list, last, extra = self.setup_joins(
    14351435                field_list, opts, self.get_initial_alias(), False)
     1436            # add any extra filters that are needed
     1437            if extra:
     1438                self.add_filter(*extra)
    14361439
    14371440            # Process the join chain to see if it can be trimmed
    14381441            col, _, join_list = self.trim_joins(source, join_list, last, False)
  • tests/regressiontests/aggregation_regress/models.py

    diff --git a/tests/regressiontests/aggregation_regress/models.py b/tests/regressiontests/aggregation_regress/models.py
    index d1f1451..e8e47b0 100644
    a b import pickle 
    33
    44from django.db import models
    55from django.conf import settings
     6from django.contrib.contenttypes import generic
     7from django.contrib.contenttypes.models import ContentType
    68
    79try:
    810    sorted
    class Book(models.Model): 
    3436    contact = models.ForeignKey(Author, related_name='book_contact_set')
    3537    publisher = models.ForeignKey(Publisher)
    3638    pubdate = models.DateField()
     39    tags = generic.GenericRelation('TaggedItem')
    3740
    3841    class Meta:
    3942        ordering = ('name',)
    class HardbackBook(Book): 
    6669    def __unicode__(self):
    6770        return "%s (hardback): %s" % (self.name, self.weight)
    6871
     72class TaggedItem(models.Model):
     73    tag = models.CharField(max_length=100)
     74    content_type = models.ForeignKey(ContentType)
     75    object_id = models.PositiveIntegerField()
     76    content_object = generic.GenericForeignKey('content_type', 'object_id')
     77
     78    def __unicode__(self):
     79        return "%s tagged with %s" % (self.content_object, self.tag)
     80
     81
    6982__test__ = {'API_TESTS': """
    7083>>> from django.core import management
    7184>>> from django.db.models import get_app, F
    __test__ = {'API_TESTS': """ 
    145158>>> Book.objects.all().aggregate(num_authors=Count('foo'))
    146159Traceback (most recent call last):
    147160...
    148 FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store
     161FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, tags
    149162
    150163>>> Book.objects.all().annotate(num_authors=Count('foo'))
    151164Traceback (most recent call last):
    152165...
    153 FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store
     166FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, tags
    154167
    155168>>> Book.objects.all().annotate(num_authors=Count('authors__id')).aggregate(Max('foo'))
    156169Traceback (most recent call last):
    157170...
    158 FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, num_authors
     171FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, tags, num_authors
    159172
    160173# Old-style count aggregations can be mixed with new-style
    161174>>> Book.objects.annotate(num_authors=Count('authors')).count()
    True 
    317330Traceback (most recent call last):
    318331...
    319332FieldError: Cannot compute Avg('mean_age'): 'mean_age' is an aggregate
    320 
     333>>> b = Book.objects.get(name='Practical Django Projects')
     334>>> _ = TaggedItem.objects.create(object_id=b.id, content_type=ContentType.objects.get_for_model(b), tag='intermediate')
     335>>> _ = TaggedItem.objects.create(object_id=b.id, content_type=ContentType.objects.get_for_model(b), tag='django')
     336>>> b = Book.objects.get(name__startswith='Paradigms of Artificial Intelligence')
     337>>> _ = TaggedItem.objects.create(object_id=b.id, content_type=ContentType.objects.get_for_model(b), tag='intermediate')
     338
     339>>> s = Store.objects.get(name__startswith='Amazon')
     340>>> _ = TaggedItem.objects.create(object_id=s.id, content_type=ContentType.objects.get_for_model(s), tag='online')
     341>>> from django.conf import settings
     342>>> settings.DEBUG = True
     343>>> from django.db import connection, reset_queries
     344>>> reset_queries()
     345>>> Book.objects.aggregate(Count('tags'))
     346{'tags__count': 3}
     347>>> connection.queries
    321348"""
    322349}
    323350
Back to Top