#10870: Aggregates with joins ignore extra filters provided by setup_joins
----------------------------------------------------------+-----------------
 Reporter:  fas                                           |       Owner:  fas   
    
   Status:  new                                           |   Milestone:        
    
Component:  ORM aggregation                               |     Version:  1.0   
    
 Keywords:  orm, aggregation, join, contenttypes, filter  |       Stage:  
Unreviewed
Has_patch:  0                                             |  
----------------------------------------------------------+-----------------
 (In case the description that follows is not understandable, please ask me
 for a better explanation).

 An example where extra filters in joins are used are reverse generic
 relations ([http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes
 /#reverse-generic-relations]).

 {{{
 class TaggedItem(models.Model):

     content_type = models.ForeignKey(ContentType)
     object_id = models.PositiveIntegerField()
     content_object = generic.GenericForeignKey('content_type',
 'object_id')


 class Bookmark(models.Model):
     url = models.URLField()
     tags = generic.GenericRelation(TaggedItem)
 }}}

 By querying {{{ Bookmark.objects.filter(tags=some_tag) }}} the generic
 relation adds extra filters to ensure the correct content type. Those
 extra filters however are ignored when using aggregates, which leads to
 wrong results.

 For example, the following query is not correct because it does not check
 the content_type.
 {{{
 Bookmark.objects.aggregate(Count('tags'))
 }}}
 What this aggregate actually calculates per bookmark is not the amount of
 tags for this bookmark but the amount of tags for any model referenced by
 TaggedItem with the same object id.

 The error is isolated in db/models/sql/query.py in the add_aggregate
 method:

 {{{
             field, source, opts, join_list, last, _ = self.setup_joins(
                 field_list, opts, self.get_initial_alias(), False)

             # Process the join chain to see if it can be trimmed
             col, _, join_list = self.trim_joins(source, join_list, last,
 False)
 }}}

 The last dummy element _ is normally named 'extra' in other uses of
 setup_joins and contains the extra filters needed to make it work. Adding
 {{{ self.add_filter(*extra) }}} after setup_joins fixes this problem.

-- 
Ticket URL: <http://code.djangoproject.com/ticket/10870>
Django <http://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to