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