Pierre B <rocambolesque...@gmail.com> wrote:
> Here's my use case: > right1 = Right() > right.left = Left() > > right2 = Right2() > right2.left = Left2() > > db.session.add(right) // automatically create the junction using MySubClass1 > and set the type field to 1 > db.session.add(right2) // automatically create the junction using MySubClass1 > and set the type field to 2 > db.session.commit() > > Basically I have a junction table associating a bunch of different tables in > my model. > I want to abstract that mechanism using relationships and polymorphism so > that I don't have to deal with that junction table while coding. > The relationships I created allow me to not have to deal with it while > selecting records but I can't get it to set the type field while inserting > records. OK, you are using the association object pattern. You cannot use “secondary” in the way that you are doing here. You need to map a relationship to MySubClass1 explicitly. To reduce verbosity, you’d then apply the association proxy pattern. Without association proxy, your association of right and left will be something like: right2 = Right2() right2.left_association = MySubClass1() right2.left_association.left = Left2() the association proxy then allows for MySubClass1() to be called automatically and you can refer to “right2.left” directly. Start with: http://docs.sqlalchemy.org/en/rel_0_9/orm/basic_relationships.html#association-object make that work completely, with the more verbose use pattern. then when that is totally working and understood, then move onto association proxy: http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/associationproxy.html > On Tuesday, March 31, 2015 at 4:11:51 PM UTC+2, Michael Bayer wrote: > > Pierre B <rocambol...@gmail.com> wrote: > > > I made a type in the Right model, here are the models again: > > if you’re referring to the behavior of Right.left when you use it in a > query, such as query(Right).join(Right.left), then the “default” value of a > Column object has no interaction there. > > it seems like you probably want to do something very simple here but I’m not > getting enough information on what that is. If you could illustrate the > usage of the objects that you are looking for, that would help. > > > > > > > > class HasSomeAttribute(object): > > @declared_attr.cascading > > def type(cls): > > if has_inherited_table(cls): > > if cls.__name__ == 'MySubClass1': > > return db.Column(db.Integer, default=1) > > else: > > return db.Column(db.Integer, default=2) > > else: > > return db.Column(db.Integer, default=0) > > > > class MyClass(HasSomeAttribute, db.Model): > > __tablename__ = 'people4l2' > > id = db.Column(db.Integer, primary_key=True) > > id1 = db.Column(db.Integer) > > id2 = db.Column(db.Integer) > > > > class MySubClass1(MyClass): > > pass > > > > class MySubClass2(MyClass): > > pass > > > > class Right(db.Model): > > id = db.Column(db.Integer, primary_key=True) > > left = relationship( > > 'Left', > > secondary= MySubClass1.__table__, > > primaryjoin='and_(MySubClass1.type == 802, MySubClass1.id2 == > > Right.id)', > > secondaryjoin='and_(MySubClass1.type == 802, MySubClass1.id1 == > > Left.id)' > > ) > > > > class Left(db.Model): > > id = db.Column(db.Integer, primary_key=True) > > > > > > On Tuesday, March 31, 2015 at 12:12:35 PM UTC+2, Pierre B wrote: > > Hi Michael, > > > > Thank you for your response. > > Unfortunately I have already tried to use the __init__ function/catch the > > init event but I am only referencing the sub classes in a relationship > > which does not seem to actually instantiate classes because the __init__ is > > never called/init event is never fired. > > Here is a simple version of my models. > > > > class HasSomeAttribute(object): > > @declared_attr.cascading > > def type(cls): > > if has_inherited_table(cls): > > if cls.__name__ == 'MySubClass1': > > return db.Column(db.Integer, default=1) > > else: > > return db.Column(db.Integer, default=2) > > else: > > return db.Column(db.Integer, default=0) > > > > class MyClass(HasSomeAttribute, db.Model): > > __tablename__ = 'people4l2' > > id = db.Column(db.Integer, primary_key=True) > > id1 = db.Column(db.Integer) > > id2 = db.Column(db.Integer) > > > > class MySubClass1(MyClass): > > pass > > > > class MySubClass2(MyClass): > > pass > > > > class Right(db.Model): > > id = db.Column(db.Integer, primary_key=True) > > subclass_attr = relationship( > > 'Contact', > > secondary= MySubClass1.__table__, > > primaryjoin='and_(MySubClass1.type == 802, MySubClass1.id2 == > > Right.id)', > > secondaryjoin='and_(MySubClass1.type == 802, MySubClass1.id1 == > > Left.id)' > > ) > > > > class Left(db.Model): > > id = db.Column(db.Integer, primary_key=True) > > > > MyClass is used as a junction table for a bunch of different relationships, > > the type field is used to differentiate the relationships. > > > > > > On Monday, March 30, 2015 at 5:26:30 PM UTC+2, Michael Bayer wrote: > > > > > > Pierre B <rocambol...@gmail.com> wrote: > > > > > Hi all, > > > > > > I'm ultimately trying to have different default values for the same > > > column. Following the documentation, the @declared_attr.cacading > > > decorator seems to be the best approach. > > > Here's my code: > > > class HasSomeAttribute(object): > > > @declared_attr.cascading > > > def type(cls): > > > if has_inherited_table(cls): > > > if cls.__name__ == 'MySubClass1': > > > return db.Column(db.Integer, default=1) > > > else: > > > return db.Column(db.Integer, default=2) > > > else: > > > return db.Column(db.Integer, default=0) > > > > > > class MyClass(HasSomeAttribute, db.Model): > > > __tablename__ = 'people4l2' > > > id = db.Column(db.Integer, primary_key=True) > > > > > > class MySubClass1(MyClass): > > > pass > > > > > > class MySubClass2(MyClass): > > > pass > > > > > > I iterated quite a few times over this but I'm systematically getting > > > this error: > > > ArgumentError: Column 'type' on class <class '__main__.MySubClass1'> > > > conflicts with existing column 'people4l2.type’ > > > > this mapping illustrates MySubClass1 and MySubClass2 as both sharing the > > same table “people4l2”, as they have no __tablename__ attribute, so there > > can only be one “type” column. So in this case it is not appropriate to use > > cascading in exactly this way, as MyClass already has a “type” column, and > > that gets attached to the “people4l2” table and that’s it; there can be no > > different “type” column on MySubClass1/MySubClass2. > > > > If you’d like “type” to do something different based on which class is > > being > > instantiated, this is an ORM-level differentiation. Use either the > > constructor __init__() to set it or use the init() event > > (http://docs.sqlalchemy.org/en/rel_0_9/orm/events.html?highlight=event%20init#sqlalchemy.orm.events.InstanceEvents.init). > > > > > > OTOH if “type” is actually the “polymoprhic discriminator”, which is what > > this looks like, then you’d be looking to just set up “type” as the > > “polymorphic_on” column and set up the “1”, “2”, “0” as the polymorphic > > identity (see > > http://docs.sqlalchemy.org/en/rel_0_9/orm/inheritance.html#single-table-inheritance > > > > for a simple example). > > > > > > -- > > 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 sqlalchemy+...@googlegroups.com. > > To post to this group, send email to sqlal...@googlegroups.com. > > Visit this group at http://groups.google.com/group/sqlalchemy. > > For more options, visit https://groups.google.com/d/optout. > > -- > 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 sqlalchemy+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at http://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. -- 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 sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.