On Aug 25, 2010, at 7:43 PM, Nigel wrote:

> Thanks very much for the quick reply.  The second suggested worked
> nicely.  I guess this explains why I was having such a hard time
> tracking down a similar situation online!
> 
> Maybe I can sneak a second question in here which is to ask why the
> many - many connection table can not be created using the declarative
> method?  Would it be normal to create the mapping for that table after
> it has been created in order to get a relational object?

A declarative mapping defines a Table, a user-defined class, and a mapper 
associating the two all at once.  In the case of "secondary", that is a Table 
that is referenced by a relationship() as an intermediary table to satisfy the 
linkage between two mappers, but is not mapped itself, has no corresponding 
user defined class, and is not subject to the same persistence methods as that 
of mapped classes.     

There is another pattern called the "association object" pattern, which removes 
the "secondary" argument and explicitly maps the intermediary table, and then 
specifies a relationship() from parent to intermediary class, then another from 
intermediary to child class.   This is a very common pattern and is used when 
additional meaningful information is present on the intermediary table, and 
there is also a helper called the "associationproxy" which can allow such a 
configuration to act like a many-to-many when that's all that's needed.

Both patterns can also be combined.   Doing so is not really necessary as the 
associationproxy is a cleaner solution, but the "secondary" method offers a 
slight performance gain when loading related rows.   If the two patterns are 
combined, you'd usually want to add "viewonly=True" to the relationship() that 
references the Table via "secondary".   If this is not done, a mutation to the 
"secondary" relationship that is mirrored by mutations to the "association" 
relationship can cause conflicting instructions during a flush.   



> 
> Thanks again,
> nigel
> 
> 
> On Aug 25, 4:20 pm, Michael Bayer <mike...@zzzcomputing.com> wrote:
>> On Aug 25, 2010, at 4:57 PM, Nigel wrote:
>> 
>> 
>> 
>>> Hi all,
>> 
>>> I'm having some trouble with using a schema with a many-to-many
>>> declarative mapping.  The error i'm getting is as follows:
>> 
>>> "
>>> sqlalchemy.exc.InvalidRequestError: One or more mappers failed to
>>> compile. Exception was probably suppressed within a hasattr() call.
>>> Message was: One or more mappers failed to compile. Exception was
>>> probably suppressed within a hasattr() call. Message was: When
>>> compiling mapper Mapper|Entity|entity, expression 'Entity.id ==
>>> entityConnections.c.masterId' failed to locate a name ("name
>>> 'entityConnections' is not defined"). If this is a class name,
>>> consider adding this relationship() to the <class '__main__.Entity'>
>>> class after both dependent classes have been defined.
>>> "
>> 
>>> Here is a bit of code that will fail. Please excuse the word wrapping:
>> 
>>> "
>>> Base = declarative_base( bind = engine )
>> 
>>> entityConnection = Table( 'entityConnections', Base.metadata,
>>> Column( 'masterId', Integer,
>>> ForeignKey( 'relationalSchema.entity.id' ), primary_key = True ),
>>> Column( 'slaveId', Integer,
>>> ForeignKey( 'relationalSchema.entity.id' ), primary_key = True ),
>>> schema = 'relationalSchema' )
>> 
>>> class Entity( Base ):
>>>    __tablename__ = 'entity'
>>>    __table_args__ = { 'schema':'relationalSchema' }
>> 
>>>    id = Column( Integer, primary_key = True )
>>>    entityType = Column(String)
>> 
>>>    connections = relationship( 'Entity', secondary = entityConnection,
>>> primaryjoin = "Entity.id == entityConnections.c.masterId",
>>> secondaryjoin = "Entity.id == entityConnections.c.slaveId",backref =
>>> 'entity' )
>> 
>>>    def __init__(self, entityType ):
>>>            self.entityType = entityType
>> 
>>>    def __repr__(self):
>>>            return "<Entity('%s')>" % ( self.entityType )
>> 
>>> from sqlalchemy.orm import sessionmaker
>>> Session = sessionmaker(bind=engine)
>>> session = Session()
>>> session.add( Entity( 'test' ) )
>>> "
>> 
>>> If I remove the references to the schema the code runs fine.  Adding
>>> the schema to the primaryjoin and secondaryjoin just changes the error
>>> so it must be something else.  Any ideas what I'm doing wrong here?
>>> I'm a rank newbie with sqlalchemy so it's probably a pretty easy thing
>>> to fix!
>> 
>> er OK you're actually doing something that has not been anticipated, and it 
>> is the "relationalSchema" bit.    So this is a bug/feature type thing in 
>> SQLAlchemy (would have to figure out how we'd like this to work - I've added 
>> ticket #1893 which would have it work as 
>> "relationalSchema_entityConnections").
>> 
>> The two workarounds at the moment are:
>> 
>>         Base.metadata.tables['entityConnections'] = entityConnection
>> 
>> or, this is certainly easier in this case, just lose the quotes:
>> 
>>     connections = relationship( 'Entity', secondary = entityConnection,
>> primaryjoin = id == entityConnection.c.masterId,
>> secondaryjoin = id == entityConnection.c.slaveId,backref =
>> 'entity' )
>> 
>> 
>> 
>>> --
>>> You received this message because you are subscribed to the Google Groups 
>>> "sqlalchemy" group.
>>> To post to this group, send email to sqlalch...@googlegroups.com.
>>> To unsubscribe from this group, send email to 
>>> sqlalchemy+unsubscr...@googlegroups.com.
>>> For more options, visit this group 
>>> athttp://groups.google.com/group/sqlalchemy?hl=en.
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To post to this group, send email to sqlalch...@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.
> 

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@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