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 sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to