On Tue, Feb 3, 2009 at 8:34 PM, Russell Keith-Magee
<[email protected]> wrote:
> On Tue, Feb 3, 2009 at 11:16 AM, [email protected]
> <[email protected]> wrote:
>>
>> On Feb 2, 9:05 pm, nsitarz <[email protected]> wrote:
>>> Hey,
>>>
>>> Back when the ORM aggregate support was a patch in trac I used to
>>> create custom aggregate objects that looked like this:
>>>
>>> class Date(Aggregate):
>>> pass
>>>
>>> class DateHour(Aggregate):
>>> def __init__(self, lookup):
>>> super(DateHour, self).__init__(lookup)
>>> self.sql_template = '(DATE(${field}) + INTERVAL HOUR(${field})
>>> HOUR)'
>>>
>>> However now that aggregate support has made its way into trunk the api
>>> seems to have changed a bit. After reading the aggregate module it
>>> looks to me like I'd have to reimplement the Aggregate class myself in
>>> order to have this same kind of functionality. Is there a supported
>>> way of creating custom aggregate classes for use with the trunk ORM?
>>>
>>> I'd appreciate any help that anybody can offer on this.
...
> What you will end up with is a backend-specific aggregate class that
> appears to be a generic aggregate for the purposes of annotate() and
> aggregate() calls.
Curiosity got the better of me... so here's a worked (and documented)
example that reimplements the Max() aggregate:
from django.db.models.sql.aggregates import Aggregate
class MyMax(Aggregate):
sql_function = 'MAX'
"""A base class to make it easy for end users to define their own
custom SQL aggregates.
The subclass should define the following two class properties:
* sql_function - the name of the SQL function to invoke
Optionally, you can define
* sql_template - a format string that is used to compose the
SQL that will be sent to the database. The template will be
provided with the following substitution variables:
- ``function``, the sql fuction that will be invoked
- ``field``, the resolved name of the column to be
operated on.
The template will also be provided with any keyword argument
provided to the aggregate when it was defined.
The default template is '%(function)s(%(field)s)'
* is_ordinal - a boolean, True if the result of the aggregate
will always be a count, regardless of the field on which the
aggregate is applied. False by default.
* is_computed - a boolean, True if the result of the aggregate
will always be a float, regardless of the field on which the
aggregate is applied. False by default.
"""
def __init__(self, lookup, **extra):
self.lookup = lookup
self.extra = extra
def _default_alias(self):
return '%s__%s' % (self.lookup, self.__class__.__name__.lower())
default_alias = property(_default_alias)
def add_to_query(self, query, alias, col, source, is_summary):
super(MyMax, self).__init__(col, source, is_summary, **self.extra)
query.aggregate_select[alias] = self
Usage:
Book.objects.annotate(MyMax('pubdate'))
Yours,
Russ Magee %-)
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---