On Sat, Apr 26, 2008 at 6:32 PM, Simon Willison <[EMAIL PROTECTED]> wrote:
>
>  On Apr 26, 7:34 am, "Ian Kelly" <[EMAIL PROTECTED]> wrote:
>  > On Fri, Apr 25, 2008 at 11:40 PM, Russell Keith-Magee
>  >
>
> > <[EMAIL PROTECTED]> wrote:
>  > >  >  Have you considered syntax that looks like this instead? :
>  > >  >  >>> Students.objects.all().aggregate({'average_height': 
> 'height__avg})
>  > >  >  > {'average_height' : 1.43}
>  >
>  > >  My issue with this syntax is that every aggregate requires 4 extra
>  > >  punctuation characters (two parentheses, two quotes), and all you
>  > >  really get in return is to reverse the order so that you get
>  > >  result=operation type syntax... except that you can't use the =
>  > >  operator. It also doesn't have any particular analogs with existing
>  > >  ORM syntax.
>  >
>  > I would say it has a pretty good analog:
>  >
>  > >>> Student.objects.all().extra(select={'floor_height': 'floor(height)'})
>
>  That was my thinking exactly. I think the cognitive dissonance
>  involved in height__avg='average_height' is much greater than that in
>  ({'average_height': 'height__avg}). Sure, it's new ORM syntax but it's
>  also a new ORM feature. Overloading the existing syntax to do
>  something that's actually quite different feels really strange to me.

I can see that there might be a bit of cognitive dissonance; however,
it doesn't bug me personally as much as the syntax your are proposing.
Excessive parentheses and quotes like that increase the possibilities
for mistyping mistakes, and don't really serve to improve clarity in
the underlying expression.

That said, the cognitive dissonance is a reasonable enough objection
to warrant some more exploration of the syntax options.

So - here's a slightly modified proposal. Last time this topic came up
on django-dev, Justin Fagnani made an interesting suggestion which I
think will answer your objections, and leaves open some interesting
possibilities for userspace extension. Rather than the
column__aggregate=alias syntax:

>>> Student.objects.all().annotate(Avg('height'),
tallest=Max('height'), avg_friend_age=Avg('friend__age')

The raw idea - the aggregates themselves are tied up into functions
(Avg, Max, etc) that are constructed as an object. The argument to the
aggregate is the query column, using the standard double-underscore
notation if necessary to cross tables. In QS-RF, this syntax is being
used for cross-table order_by() clauses, so there is an analog there.

If the aggregate function is provided as an anonymous argument (e.g.,
Avg('height')), then the aggregate is asked to provide an appropriate
alias - for example, Avg() might use 'avg__%s' % field_name. If the
aggregate function is provided as a kwarg, the kwarg name is used as
the alias.

Userspace extension becomes a lot easier - If a particular database
has an interesting aggregate that isn't supported as part of the core
set, you can write your own aggregate and use it as you see fit.

It also leaves open the door to do nifty things like
annotate(foo=Avg('a') * Sum('b')) - i.e., alegebraic expressions
between aggregates. Obviously, this sort of API will require a whole
lot of work to get right, but the option is there.

Does this proposal sound any better to you?

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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to