so, some background, "table_name" is a Rails-style polymorphic association, 
very old blog post about this at:  http://techspot.zzzeek.org/archive/2007/05/1/

So there's a hacky way there, which you can adopt to declarative, to do the 
"foreign key thats not really a foreign key" thing.    I don't like it since 
the lack of an FK means the relatoinship is entirely corruptable.   From 
reading the post you'll see i always find a way to use foreign keys correctly, 
which means an extra table.

Polymorphically, youd have FooTag, BarTag, with a joined table, the table thats 
joined has an FK back to the parent Foo or Bar.

Without using the polymorphic thing, which actually I usually don't for this, 
you can have your tags @declared_attr pull out a "secondary" table, right in 
the relationship there.   Or polymorphically you could generate FooTag, BarTag 
right there.  @declared_attr is great for all that stuff.

The polymorphic association is something I'm slowly getting ready to re-present 
in a declarative way, since its been coming up a lot lately and that blog post 
is from 2007.



On Apr 22, 2011, at 12:20 AM, Andrey Petrov wrote:

> Hi there,
> 
> I'm trying to make a table for annotating other tables' rows, perhaps even in 
> relation to a user. I haven't been able to find similar examples of this 
> elsewhere so I'd like a sanity check that I'm not doing something 
> horrendously wrong. This is in SQLAlchemy 0.7 by the way.
> 
> Here's an example:
> 
> class Tag(BaseModel):
>     __tablename__ = 'tag'
> 
>     id = Column(types.Integer, primary_key=True)
>     table_name = Column(types.String(64))
>     user_id = Column(types.Integer)
>     row_id = Column(types.Integer)
> 
>     name = Column(types.String, nullable=False)
> 
> Index('tag_backref_idx', Tag.table_name, Tag.user_id, Tag.row_id, Tag.name, 
> unique=True)
> Index('tag_name_idx', Tag.table_name, Tag.user_id, Tag.name)
> 
> So say I have a table called user, I want to be able to apply a tag to a row 
> in it as Tag(table_name='foo', user_id=None, row_id=1, name='sometag'). The 
> semantic is that user_id=None means it's a "global" (aka. system) tag, 
> whereas a tag from a user would have that user_id filled respectively.
> 
> On the Foo object, I can apply a relation like this (I'm doing this via a 
> mixin class in my code):
> 
>     @declared_attr
>     def tags(cls):
>         return orm.relationship(Tag,
>             primaryjoin=and_(
>                 Tag.table_name==cls.__tablename__,
>                 Tag.user_id==None,
>                 Tag.row_id==cls.id,
>             ),
>             foreign_keys=[Tag.table_name, Tag.user_id, Tag.row_id],   
>         )
> 
> So now I can do things like...
>  
> f = Session.query(Foo).get(1)
> f.tags # == [list of global Tag objects applied on object f]
> 
> The goal is to be able to apply a "tag" on the system level (user_id=None) or 
> on the user level for any row of any table (in reality there will be a couple 
> of tables that will never have tags, but 90% will).
> 
> My questions:
> Can we use the polymorphic_on stuff to make this better integrated?
> Is there a way to make a "dynamic" ForeignKey reference such that I can 
> associate a tag to an object that hasn't been committed (ie. no `id` yet)? 
> 
> Example:
> 
> f = Foo()
> t = Tag(name='blah', magic_triple_column_property=f)
> Session.add(f)
> Session.add(t)
> Session.commit()
> 
> Am I crazy for trying to do this? Is there a better/simpler/more rational way 
> to do something like this?
> 
> Thanks in advance!
> 
> - Andrey
> 
> -- 
> 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.

-- 
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