Russell Keith-Magee wrote: > annotate() returns a query set, so it can be used multiple times, be > combined with filters, etc. The argument handling strategy employed in > filter() is reused here; kwargs to annotate() can be decomposed on a > __ boundary to describe table joins, with the last part describing the > aggregate operator to be used. The syntax follows something like: > > Model.objects.annotate(field1__field2__aggregate='annotation')
[snip] > e.g., > # Get order 1234, and annotate it a few different ways > >>> order = Order.objects.get(id=1234).annotate( > books__price__sum='total_cost', > books__count='item_count') > # Inspect the order > >>> order.description > "Dad's birthday" > # Annotated orders have a 'total_cost' attribute... > >>> order.total_cost > 47.2 > # ... and an 'item_count' attribute > >>> order.item_count > 3 I like making the aggregate function a part of a keyword argument. It seems consistent with the Django DB API and offers a lot of flexibility. Better, in my opinion than individual functions for each aggregator. The 'annotate' name is a little indirect. Maybe something like 'calc_fields'? > 3. Just the facts, Ma'am > ~~~~~~~~~~~~~~~~~~~~~~~~ > Ok; so what if you just want _the minimum_, or _the average_? For > this, I propose an aggregates() queryset modifier. > > >>> Book.objects.aggregates(price__min='min_price', > >>> pub_date__max='last_update') > {'min_price':0.5, 'last_update': 2006-11-22} > > aggregates() would expand queries in the same manner as annotate(), > but would be a terminal clause, just like the values() clause. > > This is a more verbose notation than the simple 'max()/min()' . I have > discussed my problems with these operators previously; however, if > there is sufficient demand, I don't see any reason that min('field') > couldn't be included in the API as a shorthand for > Model.objects.aggregates(field__min='min')['min']. This seems good, too, but maybe call it 'calc_values' or something with the 'values' name in it to be consistent with the existing values() method. The shortcut is nice but I could live without it. > 4. Comparisons > ~~~~~~~~~~~~~~ > There is one additional requirement I can see; to perform queries like > (c), you need to be able to compare annotation attributes to object > attributes. > > # Annotate a query set with the average price of books > >>> qs = Book.objects.annotate(price__average='avg_price'). > # Filter all books with obj.avg_price < obj.price > >>> expensive_books = qs.filter(avg_price__lt=F('price')) > > The F() object is a placeholder to let the query language know that > 'price' isn't just a string, it's the name of a field. This follows > the example of Q() objects providing query wrappers. To make it more like Q(), would it be better to do F(avg_price__lt='price') so you could combine them with | and &? --~--~---------~--~----~------------~-------~--~----~ 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 [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~----------~----~----~----~------~----~------~--~---