i think this should be it:
http://www.sqlalchemy.org/docs/04/plugins.html#plugins_associationproxy

and relevant discussion here:
http://groups.google.com/group/sqlalchemy/browse_thread/thread/52565295f54fd85/31f53dca1e31e5ee?hl=en&lnk=gst&q=mapper+for+two+tables#31f53dca1e31e5ee


On Oct 2, 3:50 pm, rca <[EMAIL PROTECTED]> wrote:
> Thanks again, it is much appreciated
>
> On Oct 2, 1:03 pm, [EMAIL PROTECTED] wrote:
>
> > if the tables have nothing in common, u can have a MapperExtension
> > that when touching one item updates the proper table.
> > as a working big example,
> > see sqlalachemyAggregator, either inhttp://dev.gafol.net/t/aggregator
> > orhttp://dbcook.svn.sourceforge.net/viewvc/dbcook/trunk/dbcook/misc/agg...
> > which does things like counting summing etc
> > runtime-updates-of-some-cache.
> > but i'm not sure if that is what u want; imo u need it more explicit
> > than this..
>
> I have the same feeling (much less assertive here, me, the sql/alchemy
> noop)
> but i will study the example
>
>
>
> > and i still cant see how obj.surface=xyz will lookup and populate
> > surface_id. imo u need 3 attributes:
> >  - _surface_text - table1.surface, hidden
> >  - _surface_id  - table2.surface, hidden
> >  - surface: property which is visible and does the dispatch/lookup etc
>
> yes, the three attributes, i am able to do this now - what I am unable
> is to map them to different tables -- and be persisted when
> session.save(obj) -- and
> session.query(obj).filter(obj.attribute_from_the_second_table)
> It must be something stupid, i will try to come with an example
>
>
>
> > ciao
>
> > On Thursday 02 October 2008 13:59:40 rca wrote:
>
> > > thanks for the pointer, I tried and finally managed something the
> > > synonym (with the big neon "don't panic" in my head)
>
> > > I can do the conversion and insert "integers id" in place of
> > > "textual representation" and when accessing the parameter .surface,
> > > get the textual representation instead of id
> > > In this way, it works the same as my own type, but just more
> > > flexible (it can access other parameters of the object).
>
> > > But still... is there a way to map one class to two tables in one
> > > go?
>
> > > To have :
> > >   obj.surface_id --> table1.surface_id
> > >   obj.surface --> table2.surface
>
> > > when you do:
> > >   obj.surface = "XXX"
> > >   obj.name="YYY"
> > > to have sqlachemy do:
> > >   "UPDATE table2 SET surface='XXX' WHERE table2.id = 2" (this is a
> > > foreign key, the value is in the table1.surface_id)
> > > *AND*
> > >   "UPDATE table1 SET name='YYY' WHERE table1.id = 8"
>
> > > i am getting this, which is wrong, because surface is foreign key,
> > > an integer:
> > > SELECT s1.* FROM table1 AS s1 WHERE s2.surface_id = 'XXX'
>
> > > if using the custom type, i am able to translate the attribute to
> > > its id, and use it in the query, yet the synonym might be better,
> > > only if it was possible to do
> > > session.query(Object).filter(Object.surface== "XXX")
> > > and get: SELECT s1.*, s2.* FROM table1 AS s1 LEFT JOIN table2 AS s2
> > > ON s1.surface_id = s2.id WHERE s2.surface = 'XXX'
>
> > > remember, my goal was to use obj.surface = "XXX" and have this
> > > value referenced from the other table.
>
> > > Sorry if my questions are stupid!
>
> > > --roman
>
> > > On Oct 1, 10:21 am, [EMAIL PROTECTED] wrote:
> > > > maybe try, instead of hiding the conversion inside db-types
> > > > layer, to move it upper, i.e. make it a real reference/FK-column
> > > > to real object/table, then make a python property (see "synonim")
> > > > to do the conversion.
>
> > > > On Tuesday 30 September 2008 23:20:16 rca wrote:
> > > > > Hi all,
>
> > > > > my apologies for a long question, I am new to sqlalchemy and I
> > > > > was struggling with one problem. I solved it but I really not
> > > > > sure it's the right way to do it.
>
> > > > > The problem is that I need to create objects like this:
> > > > > Token(pos=2, surface="helloWorld")
>
> > > > > The surface is string, but in the database, it should be saved
> > > > > as reference to an other table (looked-up and saved if not
> > > > > existing)
>
> > > > > The way I solved it was to create my own column type decorating
> > > > > Integer. On the way in, it gets text and stores id, on the way
> > > > > out, it gives the text back.
>
> > > > > But I don't know if my solution is safe. For instance,
> > > > > -- I am decorating Integer type, but on the output there is
> > > > > string. -- I am using the EntitySingleton recipy, but I found
> > > > > out I could not use the recommended
> > > > > Session = scoped_session(sessionmaker())
> > > > > I had to say: Session = sessionmaker()
> > > > > -- And I do commit for every new looked-up value
>
> > > > > And also, I have the impression the solution is very
> > > > > complicated, perhaps you could help me to do it in a better
> > > > > way.
>
> > > > > Many thanks!
>
> > > > >   roman
>
> > > > > Here is the code with an example:
> > > > > -------------------------------------------------------
>
> > > > > import sqlalchemy as sa
> > > > > from sqlalchemy.ext.declarative import declarative_base
> > > > > from sqlalchemy.orm import scoped_session, sessionmaker,
> > > > > relation, backref, mapper
> > > > > from sqlalchemy import create_engine, Table, Column, Integer,
> > > > > String, MetaData, ForeignKey
> > > > > #from mimetypes import types_map
> > > > > import weakref
> > > > > import sqlalchemy.types as types
>
> > > > > Session = sessionmaker()  #scoped_session(sessionmaker)
>
> > > > > DBase = declarative_base()
>
> > > > > class MyUnique(types.TypeDecorator):
> > > > >     """a type that decorates Integer,
> > > > >     receives a text representation - eg. MyValueFromEnumeration
> > > > >     and replaces it in the database with id of the string above
> > > > >     It makes sure that inserted values are unique (creates them
> > > > > if not exist)"""
>
> > > > >     impl = types.Integer
>
> > > > >     def process_bind_param(self, value, dialect):
> > > > >         #ukladani do databaze
> > > > >         if not hasattr(self, '__unique_valuee'):
> > > > >             self.__unique_valuee = Surface(value)
> > > > >         return self.__unique_valuee.id
>
> > > > >     def process_result_value(self, value, dialect):
> > > > >         #vystup
> > > > >         return self.__unique_valuee.surface
>
> > > > >     """ #if it is string type
> > > > >     def copy(self):
> > > > >         return MyUniqueString(self.impl.length)
> > > > >     """
>
> > > > > class DocumentBase(object):
> > > > >     def __init__(self):
> > > > >         self.metadata = DBase.metadata
> > > > >         self.engine = None
>
> > > > >     def open(self, url='sqlite:///:memory:'):
> > > > >         self.engine = create_engine(url, echo=True)
> > > > >         #engine = create_engine('sqlite:///' + __file__ +
> > > > > ".db", echo=True)
> > > > >         Session.configure(bind=self.engine)
> > > > >         self.metadata.bind = self.engine
>
> > > > >         surface_table = sa.Table('surface', self.metadata,
> > > > >             sa.Column('id', sa.Integer, primary_key=True,
> > > > > autoincrement=True),
> > > > >             sa.Column('surface', sa.String(500),
> > > > > autoincrement=True) )
>
> > > > >         mapper(Surface, surface_table)
>
> > > > >         self.metadata.create_all(checkfirst=True)
>
> > > > >     def add(self, document_object):
> > > > >         sess = Session()
> > > > >         sess.save_or_update(document_object)
> > > > >         sess.commit()
>
> > > > > class EntitySingleton(type):
> > > > >     """a metaclass that insures the creation of unique and non-
> > > > > existent entities for
> > > > >     a particular constructor argument.  if an entity with a
> > > > > particular constructor
> > > > >     argument was already created, either in memory or in the
> > > > > database, it is returned
> > > > >     in place of constructing the new instance."""
>
> > > > >     def __init__(cls, surface, bases, dct):
> > > > >         cls.instances = weakref.WeakValueDictionary()
>
> > > > >     def __call__(cls, surface):
> > > > >         session = Session()
>
> > > > >         hashkey = surface
> > > > >         try:
> > > > >             return cls.instances[hashkey]
> > > > >         except KeyError:
> > > > >             instance =
> > > > > session.query(cls).filter(cls.surface==surface).first()
> > > > >             if instance is None:
> > > > >                 instance = type.__call__(cls, surface)
> > > > >                 #session.begin_nested()
> > > > >                 session.add(instance)
> > > > >                 session.commit()
> > > > >                 # optional - flush the instance when it's saved
> > > > >                 session.flush([instance])
> > > > >             cls.instances[hashkey] = instance
> > > > >             return instance
>
> > > > > class Document(DBase):
> > > > >     __tablename__ = 'documents'
> > > > >     id = sa.Column(sa.Integer(9), primary_key=True,
> > > > > autoincrement=True)
> > > > >     name = sa.Column(sa.String(500))
> > > > >     uri = sa.Column(sa.String(500))
> > > > >     processing_stage = sa.Column(sa.String(500))
>
> > > > >     tokens = relation("Token", backref="Document")
>
> > > > >     def __xinit__(self, name):
> > > > >         self.name = name
> > > > >     def __repr__(self):
> > > > >         return "<%s('%s','%s')>" % (self.__class__, self.id,
> > > > > self.name)
>
> > > > > class Token(DBase):
> > > > >     __tablename__ = 'tokens'
> > > > >     id = sa.Column(sa.Integer(6), primary_key=True,
> > > > > autoincrement=True)
> > > > >     pos = sa.Column(sa.Integer(6))
> > > > >     type = sa.Column(sa.String(500))
> > > > >     surface = sa.Column(MyUnique(500),
> > > > > sa.ForeignKey('surface.id')) surface_translated =
> > > > > sa.Column(sa.String(500))
> > > > >     sem = sa.Column(sa.String(500))
>
> > > > >     title_id = sa.Column(sa.Integer,
> > > > > sa.ForeignKey('documents.id')) #document = relation("Document",
> > > > > backref="Token")
>
> > > > >     #def __init__(self, surface=None, **kwargs):
>
> > > > >     def __repr__(self):
>
> ...
>
> read more »
--~--~---------~--~----~------------~-------~--~----~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to