On Jan 26, 2009, at 1:29 PM, Toby Bradshaw wrote:
>
> Michael Bayer wrote:
>> also your example should read like this:
>>
>> a = session.query(A).all()[0]
>> print a.time_units
>> a.time_units = 1
>> print a.time_units
>> #print A.timeunits
>> #print A.time_units
>>
> Huh ? time_units is the column name in the database. I want to refer
> to
> that column through the attribute 'timeunits'. I also want to use
> descriptors to do extra work when setting that attribute. The synonym
> api docs say:
>
> *def synonym(/name/, /map_column=False/, /descriptor=None/, /
> proxy=False/)*
> Set up name as a synonym to another mapped property.
>
> So when I say:
>
> mapper(A, table_A, properties = {
> "time_units" : synonym("timeunits", map_column = True)
> })
>
>
> Am I not saying 'create an alias to column 'time_units' in table_A and
> call it 'timeunits' ??
I think your confusion is focused on the concept of SQLAlchemy
instrumented descriptors, as it seems you're expecting the SQLAlchemy
column-mapped descriptor to "wrap" an existing descriptor. This is
not how it works. SQLAlchemy does not populate instance state
using getattr()/setattr(), in the default case it populates __dict__
directly. The dictionary which it uses can be wrapped with a user-
defined "proxying" dictionary but that's not an API you need to get
involved with. By moving all low-level operations to __dict__ and
all in-python operations to instrumented descriptors, the separation
of event-producing attribute access and direct en-masse state access
is clear, and the very high-volume activity of populating object state
is performed without the overhead of setattr() or event production.
The "synonym" model is provided so that a user-defined descriptor and
a SQLAlchemy-column mapped descriptor can co-exist, but instead of
being wrapped, they use different names. So usage of the model
means: one descriptor maps to the column and is entirely generated by
SQLAlchemy, the other is your custom descriptor and SQLAlchemy places
a proxy around it to provide class-level behavior like Foo.bar ==
somevalue (which you also might want to customize, but that's a
different issue). Your custom descriptor is the public face of the
attribute, and communicates with the value that exists in the database
using the column-mapped descriptor, which is usually treated as
private. Symmetric set/get behavior is provided by the user-defined
descriptor as the sole public interface.
So since you'd like to refer to the *translated* attribute as
"timeunits", i think you'd want to configure this way:
class MyClass(object):
...
timeunits = property(_get, _set)
mapper(MyClass, table, properties={
"_timeunits":table.c.time_units,
"timeunits": synonym("_timeunits")
})
which will map the original "time_units" column to the mapped
attribute "_timeunits", and the "timeunits" descriptor will provide
class-level comparison behavior (i.e. MyClass.timeunits == 5). the
map_column flag does not apply here since you are naming your
descriptor something different than the original mapped column. The
column-mapped attribute "_timeunits" is generally treated as
"private" within the application space since it represents directly
the "raw" data that is populated/retrieved to/from the database.
you can also leave "time_units" mapped under its own name:
mapper(MyClass, table, properties={
"timeunits": synonym("time_units")
})
in which case your descriptor would communicate raw values to/from the
"time_units" attribute, which is mapped automatically to its own name.
Also consider that direct translation of a single column can be
accomplished at the Table level using a custom TypeDecorator. If you
went with that route, there would be no need to use synonym() or
custom descriptors.
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---