It's better with the attachments (the actual patch and a small demonstration/test file)...
On 4/25/07, Gaetan de Menten <[EMAIL PROTECTED]> wrote:
> Ok, I'm quite a bit stubborn at times, so I implemented this the way I
> thought because I think it makes much more sense this way.
>
> Attached is an experimental (as usual) patch to add a
> StatementProperty, so that you can define stuff like:
>
> mapper(Tag, tags_table, properties={
> 'query_score': StatementProperty((tags_table.c.score1 *
> tags_table.c.score2).label('tag_score'), Float()),
> })
>
> or even:
>
> user_score = select([func.sum(tags_table.c.score1 *
> tags_table.c.score2)],
> tags_table.c.user_id == users_table.c.id,
> scalar=True).label('user_score')
>
> mapper(User, users_table, properties={
> 'tags': relation(Tag, backref='user', lazy=False),
> 'query_score': StatementProperty(user_score, Float()),
> })
>
> I don't see what's wrong with this approach so far. As always, I might
> not see the big picture... I just hope this will be useful in some
> way, even if it's not what you envisioned.
>
> Some random remarks:
> - the statement you give must have a label (that seem pretty logical
> this way though)
> - you need to manually provide the type of the property you create
> (seem logical too). In a final patch, we'd probably want to also
> accept types in their class form (Float and Float()).
> - it works both for lazy and eagerloads (I struggled quite a bit to
> get those to work)
> - subselects pulled from a lazyload don't work though. But I think it
> should be quite easily fixable.
> - As always, I'm not attached to the names I've given.
>
> On 4/24/07, Michael Bayer <[EMAIL PROTECTED]> wrote:
> >
> >
> > On Apr 24, 2007, at 4:44 AM, Gaetan de Menten wrote:
> >
> > >
> > >> the next way is to do it almost the same as Jonathan's blog says to
> > >> do it, except youd map the relation to some intermediary class like
> > >> "Score", and then use AssociationProxy to apply the "scalar" property
> > >> to the class.
> > >
> > > I thought about something like this but it felt sooo hacky I
> > > disregarded it quickly.
> > >
> >
> > this is probably the least hacky as like i said im probably going to
> > implement a feature that works just like this.
> >
>
>
>
> --
> Gaëtan de Menten
> http://openhex.org
>
--
Gaëtan de Menten
http://openhex.org
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sqlalchemy" 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/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---
from sqlalchemy import *
from sqlalchemy.orm.properties import StatementProperty
metadata = MetaData()
users_table = Table('users', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(16)),
)
tags_table = Table('tags', metadata,
Column('id', Integer, primary_key=True),
Column('user_id', Integer, ForeignKey("users.id")),
Column('score1', Float),
Column('score2', Float),
)
metadata.connect('sqlite:///')
metadata.create_all()
class User(object):
def __init__(self, name):
self.name = name
@property
def prop_score(self):
return sum(tag.prop_score for tag in self.tags)
class Tag(object):
def __init__(self, score1, score2):
self.score1 = score1
self.score2 = score2
@property
def prop_score(self):
return self.score1 * self.score2
# this doesn't work
tag_score = select([tags_table.c.score1 * tags_table.c.score2],
scalar=True).label('tag_score')
mapper(Tag, tags_table, properties={
# this doesn't work. It seems like the inside of a select is not aliasized.
# 'query_score': StatementProperty(tag_score, Float()),
'query_score': StatementProperty((tags_table.c.score1 *
tags_table.c.score2).label('tag_score'),
Float()),
})
user_score = select([func.sum(tags_table.c.score1 *
tags_table.c.score2)],
tags_table.c.user_id == users_table.c.id,
scalar=True).label('user_score')
mapper(User, users_table, properties={
'tags': relation(Tag, backref='user'),
# 'tags': relation(Tag, backref='user', lazy=False),
'query_score': StatementProperty(user_score, Float()),
})
u1 = User('joe')
t1 = Tag(5.0, 3.0)
t2 = Tag(55.0, 1.0)
u1.tags = [t1, t2]
u2 = User('bar')
t3 = Tag(5.0, 4.0)
t4 = Tag(50.0, 1.0)
t5 = Tag(15.0, 2.0)
u2.tags = [t3, t4, t5]
session = create_session()
session.save(u1)
session.save(u2)
session.flush()
session.clear()
metadata.engine.echo = True
users = session.query(User).select()
print
for user in users:
print "===%s===" % user.name
print "totals: query=%s | property=%s" % (user.query_score, user.prop_score)
print
for tag in user.tags:
print "%s * %s => query=%s | property=%s" % (tag.score1, tag.score2, tag.query_score, tag.prop_score)
# ideally, I'd like to reuse the score property on tag in the score property on
# users, and also I need to be able to defer/undefer those properties
statement_property.diff
Description: application/text
