I'm used to using aggregate types in postgres as a convenience. I
whipped up the beginings something analogous to that for django. It
allows definition of "aggregate fields" using a marker base class; it
defines a mixin for Model-derived classes that unpacks "aggregates" and
adds them as individual fields with name prefix at class creation time.

This causes the DB to generate correctly. Still to do: write
descriptors for the original thing to get the values back.

I'm interested in comments: is this a useful feature for anyone else?
Is this the best way to do this? (I'm posting now, before I've
finished, in case someone wants to dissuade me from this approach.)

I should note I found the code in django.db.models to be... relatively
straightforward... but with no obvious hooks for
customization/extension (let alone documentation for this). How do I
implement a custom field type for my favorite db (except as I've just
done: by "cheating", and translating it into already supported things)?

Of course, I should add that django is wonderfully useful, and I
realize that no ones getting paid and the version number is low, so
please don't think I'm complaining.

#
----------------------------------------------------------------------
# Aggregates:
#
----------------------------------------------------------------------
from django.db.models.base import ModelBase

class AggregateField:
    """a marker to signal that a given attribute is actually an
    aggregate of fields."""

class WithAggregatesBase( ModelBase ):
    def __init__( cls, name, bases, attrs ):
        # check if we are really a 'Model'
        for base in bases:
            if issubclass( base, Model ): break
        else:
            return super( WithAggregatesBase, cls ).__init__(
                cls, name, bases, attrs )

        # add parts of aggregates
        for atname, at in attrs.items():
            if isinstance( at, AggregateField ):
                prefix = atname.lower() + '_'
                for agname, ag in at.__class__.__dict__.iteritems():
                    fullAgname = prefix + agname
                    if fullAgname not in attrs:
                        attrs[ prefix + agname ] = copy( ag )
                        cls.add_to_class( fullAgname, ag )

        super( WithAggregatesBase, cls ).__init__(
            cls, name, bases, attrs )


class WithAggregates( object ):
    """inherit from this AND Model if you want aggregates to be
expanded."""
    __metaclass__ = WithAggregatesBase
#
----------------------------------------------------------------------
# Usage Example
#
----------------------------------------------------------------------
class Name( AggregateField ):
    first : CharField( maxlength = 60 )
    last : CharField( maxlength = 60 )

class Person( Model, WithAggregates ):
    name = Name()

-------------------------------------------------
In database, will have name_last, and name_first fields generated.

X-Google-Language: ENGLISH,ASCII-7-bit
Received: by 10.11.88.14 with SMTP id l14mr31623cwb;
        Sat, 20 May 2006 22:40:03 -0700 (PDT)
X-Google-Token: JSgsFgwAAABEMmN3KIpV7PvK92So1gxc
Received: from 66.92.72.228 by u72g2000cwu.googlegroups.com with HTTP;
        Sun, 21 May 2006 05:40:03 +0000 (UTC)
From: "shaunc" <[EMAIL PROTECTED]>
To: "Django developers" <[email protected]>
Subject: aggregate field types
Date: Sat, 20 May 2006 22:40:03 -0700
Message-ID: <[EMAIL PROTECTED]>
User-Agent: G2/0.2
X-HTTP-UserAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.3) 
Gecko/20060426 Firefox/1.5.0.3,gzip(gfe),gzip(gfe)
Mime-Version: 1.0
Content-Type: text/plain

I'm used to using aggregate types in postgres as a convenience. I
whipped up the beginings something analogous to that for django. It
allows definition of "aggregate fields" using a marker base class; it
defines a mixin for Model-derived classes that unpacks "aggregates" and
adds them as individual fields with name prefix at class creation time.

This causes the DB to generate correctly. Still to do: write
descriptors for the original thing to get the values back.

I'm interested in comments: is this a useful feature for anyone else?
Is this the best way to do this? (I'm posting now, before I've
finished, in case someone wants to dissuade me from this approach.)

I should note I found the code in django.db.models to be... relatively
straightforward... but with no obvious hooks for
customization/extension (let alone documentation for this). How do I
implement a custom field type for my favorite db (except as I've just
done: by "cheating", and translating it into already supported things)?

Of course, I should add that django is wonderfully useful, and I
realize that no ones getting paid and the version number is low, so
please don't think I'm complaining.

#
----------------------------------------------------------------------
# Aggregates:
#
----------------------------------------------------------------------
from django.db.models.base import ModelBase

class AggregateField:
    """a marker to signal that a given attribute is actually an
    aggregate of fields."""

class WithAggregatesBase( ModelBase ):
    def __init__( cls, name, bases, attrs ):
        # check if we are really a 'Model'
        for base in bases:
            if issubclass( base, Model ): break
        else:
            return super( WithAggregatesBase, cls ).__init__(
                cls, name, bases, attrs )

        # add parts of aggregates
        for atname, at in attrs.items():
            if isinstance( at, AggregateField ):
                prefix = atname.lower() + '_'
                for agname, ag in at.__class__.__dict__.iteritems():
                    fullAgname = prefix + agname
                    if fullAgname not in attrs:
                        attrs[ prefix + agname ] = copy( ag )
                        cls.add_to_class( fullAgname, ag )

        super( WithAggregatesBase, cls ).__init__(
            cls, name, bases, attrs )


class WithAggregates( object ):
    """inherit from this AND Model if you want aggregates to be
expanded."""
    __metaclass__ = WithAggregatesBase
#
----------------------------------------------------------------------
# Usage Example
#
----------------------------------------------------------------------
class Name( AggregateField ):
    first : CharField( maxlength = 60 )
    last : CharField( maxlength = 60 )

class Person( Model, WithAggregates ):
    name = Name()

-------------------------------------------------
In database, will have name_last, and name_first fields generated.


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" 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-developers
-~----------~----~----~----~------~----~------~--~---

Reply via email to