Hi all, I've been working my way through a couple of aggregation tickets, and I've hit a bit of an inconsistency that I think may need to be addressed. The problem lies in the interaction of values() and annotate(), especially as compared to the interaction of extra() and values().
Ordinarily, values() directs the ORM to return the raw values, rather than an object instance. values('x','y','z') directs the ORM to return only the named columns x,y, and z. If the query has an extra clause(), values('x','y','z') will only return the nominated columns. If an extra select column isn't mentioned specifically in the values clause, it isn't included in the result set. However, if the query contains an annotate() clause, the annotated value is always returned in the values() set, regardless of whether it is mentioned in the values clause or not. Aside from this being inconsistent, it's a little inconvenient when it interacts with the behaviour introduced in [9701] - the ability to use querysets as rvalues for __in queries. If you have a query with an annotate in it, you essentially can't use it as an rvalue, because it will always have a minimum of 2 columns, which means you can't use a query with an annotation in an __in clause (which require a single column). So - the initial suggestion here is to modify ValuesQuerySet so that annotations aren't automatically included in the result set - you would need to specifically mention the annotate column in order for it to be returned. There is a slight complication, though. The ordering of values() and annotate() is significant - values() controls the grouping of annotated values if it precedes the annotate(). However, you can't mention the annotated column in a values() clause before it is specified, so are left in a situation where you can't actually return the annotated value. For example in the query: >>> Book.values('title','isbn').annotate(n_authors=Count('authors')) n_authors wouldn't be returned in the result set, and there isn't any way to add it to the returned values. So - some options: 1) Leave things as-is. Annotated columns always appear in the result set. This is inconsistent with extra(), and means you can't use annotated queries in __in clauses. 2) Modify things slightly - annotate() calls before a values() call aren't automatically added to the results, but annotate() calls after values() are included automatically. This would allow annotations to always be returned, optionally under those circumstances that allow (i.e., annotate() before values()). 3) Rely on multiple calls to values() to get annotate columns into the result set. i.e., the previous example would need to become something like: >>> Book.values('title','isbn').annotate(n_authors=Count('authors')).values('title','isbn','n_authors') This has the potential to be a bit fragile - we would need to put in all sorts of checks for changes in column lists between successive calls to values() - but it would allow all combinations of annotation. Opinions? Any other options I may have missed? Yours Russ Magee %-) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~----------~----~----~----~------~----~------~--~---