because the event is the public, stable API ;).   I’d prefer the _set_parent() 
is a no-op but at the moment there’s a NotImplementedError in there.


On Jan 13, 2014, at 3:22 PM, Alessandro Molina <[email protected]> 
wrote:

> Looks good, just one curiosity, is there a reason for using 
> "after_parent_attach" event instead of directly using _set_parent to register 
> the LazyForeignKey for being resolved?
> 
> 
> 2014/1/13 Michael Bayer <[email protected]>
> 
> On Jan 13, 2014, at 1:19 PM, Alessandro Molina <[email protected]> 
> wrote:
> 
>> Just noticed that SQLAlchemy 0.9 broke a LazyForeignKey class that was 
>> provided by TurboGears tgext.pluggable to make possible to declare foreign 
>> keys to models not yet defined at the time the ForeignKey was declared.
>> 
>> The main use was something like:
>> 
>> class User(DeclarativeBase):
>>     __tablename__ = 'users'
>> 
>>     registration_id = Column(Integer, LazyForeignKey(lambda: 
>> app_model.Registration.uid))
>> 
>> where app_model.Registration was available only at runtime and not when User 
>> class was declared.
>> Also app_model.Registration table name was not known (as it dynamically 
>> generated to avoid collision between tables of multiple apps plugged at 
>> runtime), so it was not possible to declare the foreign key as a string with 
>> the "tablename.column_name" syntax.
>> 
>> LazyForeignKey was simply implemented as a subclass of ForeignKey which 
>> provided a custom _colspec property which would resolve the given function 
>> whenever it was first accessed: 
>> https://github.com/TurboGears/tgext.pluggable/blob/master/tgext/pluggable/sqla/relations.py#L4
>> 
>> This approach doesn't work anymore in SQLA 0.9 as _colspec gets accessed by 
>> the ForeignKey constructor itself, calling the lambda at Column declaration 
>> time.
>> 
>> It seems to me that adapting the LazyForeignKey class to SQLA 0.9 would 
>> require messing a lot more with SQLAlchemy internal code, which is something 
>> I would like to avoid. 
>> 
>> What would be the suggested way to achieve the same feature on SQLA 0.9?
> 
> Well if the table name were known, then you wouldn’t need such a feature in 
> the first place as you can just put a string name in ForeignKey().
> 
> However, as this seems to be a case where a table + declared class is to 
> eventually refer to some other Table whose name is not known yet, the 
> ForeignKey() should not exist on the Column at all until that other Table is 
> available.    A simple call to 
> User.__table__.append_constraint(ForeignKeyConstraint(<now you know what to 
> put here>)) at the time this information is known would be the cleanest.   
> 
> to get at this you’d need to use events.  First a way to make an XYZ() object 
> that can be placed inside of Column and know about it:
> 
> 
> from sqlalchemy.schema import SchemaItem
> from sqlalchemy import event
> 
> class MyThing(SchemaItem):
>     def _set_parent(self, parent):
>         pass
> 
> @event.listens_for(MyThing, "after_parent_attach")
> def my_thing_attached(target, parent):
>     print("Attaching target %s to parent %s", target, parent)
> 
> from sqlalchemy import Table, MetaData, Column, Integer
> 
> Table('t', MetaData(), Column('x', Integer, MyThing()))
> 
> Then you want to register your LazyForeignKey object in a registry that will 
> allow the callable to be invoked once your “table setup” system has completed 
> - you’d call the callable, construct a ForeignKeyConstraint, then append it 
> to the constraints of the parent column.table.
> 
> the only private API in use here is the _set_parent() override.   If I change 
> that API it would be something simple.
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/groups/opt_out.

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to