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.

Reply via email to