Thank you for your fast reply and bug fix. I will test this tonight. Cheers,
Julien. On Tue, Sep 28, 2010 at 6:46 PM, Michael Bayer <mike...@zzzcomputing.com> wrote: > this is a bug, ticket #1930, fixed in r36755ba72782. Note that a similar > issue exists for joined table inheritance, and a scheme like the below will > continue to fail if __tablename__ is added to subclasses (this is ticket > #1931). The specific "scheme" is that the attribute name of the column in > the mixin does not match the column name itself. > > http://www.sqlalchemy.org/trac/ticket/1930 > http://www.sqlalchemy.org/trac/ticket/1931 > > > > On Sep 28, 2010, at 12:06 PM, Julien Iguchi-Cartigny wrote: > >> Hello Michael, >> >> Sorry I missing something but still trap in this problem. >> >> As far as I am: >> >> class AbstractContainer(Base,AbstractNamed): >> __tablename__ = 'CM_MEMBER_CONTAINER_T' >> id = Column('MEMBER_CONTAINER_ID',Integer,primary_key=True) >> discriminator = Column('CLASS_DISCR', String(100)) >> __mapper_args__ = {'polymorphic_on': discriminator } >> >> class CourseSet(AbstractContainer): >> >> �...@classproperty >> def __mapper_args__(self): >> args = dict() >> args.update(AbstractContainer.__mapper_args__) >> args.update({'polymorphic_identity': >> 'org.sakaiproject.coursemanagement.impl.CourseSetCmImpl'}) >> return args >> >> The inheritance pass is : Course <- AbstractContainer <- AbstractNamed >> <- AbstractPersistence (see my first email for the definitions of the >> last two classes). >> >> Still having some trouble: >> >> sqlalchemy.exc.ArgumentError: Column 'VERSION' on class <class >> '__main__.CourseSet'> conflicts with existing column >> 'CM_MEMBER_CONTAINER_T.VERSION' >> >> It I understand correctly, AbstractContainer has already mapped all >> columns declared in parent classes. So CourseSet tries to remap >> everything (it herits from Base) but it fails because all column are >> already mapped. >> >> So I must say something like "hey, let just reuse mapping and table >> definitions from AbstractContainer" but how can i do this ? >> >> It seems it is very simple from the POV of the documentation, so I >> must deduce the problem comes from the multiple inheritance. >> >> Cheers, >> >> Julien. >> >> PS: This is the full listing of my code: >> >> from sqlalchemy import create_engine, Column, String, Date, Integer >> from sqlalchemy.orm import sessionmaker >> from sqlalchemy.ext.declarative import declarative_base >> from sqlalchemy.ext.declarative import has_inherited_table >> from sqlalchemy.util import classproperty >> >> engine = create_engine( >> 'mysql://xxx:y...@localhost:3306/zzz?charset=utf8&use_unicode=0', >> pool_recycle=3600, echo=True) >> >> Base = declarative_base() >> >> class AbstractPersistent(object): >> version = Column('VERSION', Integer) >> last_modified_by = Column('LAST_MODIFIED_BY', String(255)) >> last_modified_date = Column('LAST_MODIFIED_DATE', Date) >> created_by = Column('CREATED_BY', String(255)) >> created_date = Column('CREATED_DATE', Date) >> >> def __repr__(self): >> return "<AbstractPersistent('%s','%s', '%s','%s','%s')>" % \ >> (self.version, self.last_modified_by, >> self.last_modified_date, >> self.created_by, self.created_date) >> >> class AbstractNamed(AbstractPersistent): >> eid = Column('ENTERPRISE_ID', String(255)) >> title = Column('TITLE', String(255)) >> description = Column('DESCRIPTION', String(255)) >> >> def __repr__(self): >> return "<AbstractNamed('%s','%s', '%s')>" % \ >> (self.eid, self.title, self.description) + \ >> super(AbstractNamed, self).__repr__() >> >> class AbstractContainer(Base,AbstractNamed): >> __tablename__ = 'CM_MEMBER_CONTAINER_T' >> id = Column('MEMBER_CONTAINER_ID',Integer,primary_key=True) >> discriminator = Column('CLASS_DISCR', String(100)) >> __mapper_args__ = {'polymorphic_on': discriminator } >> >> class AcademicSession(Base,AbstractNamed): >> __tablename__ = 'CM_ACADEMIC_SESSION_T' >> id = Column('ACADEMIC_SESSION_ID',Integer,primary_key=True) >> start_date = Column('START_DATE', Date) >> end_date = Column('END_DATE', Date) >> >> def __repr__(self): >> return "<AcademicSession('%s','%s', '%s')>" % \ >> (self.id, self.start_date, self.end_date) + \ >> super(AcademicSession, self).__repr__() >> >> class CourseSet(AbstractContainer): >> >> �...@classproperty >> def __mapper_args__(self): >> args = dict() >> args.update(AbstractContainer.__mapper_args__) >> args.update({'polymorphic_identity': >> 'org.sakaiproject.coursemanagement.impl.CourseSetCmImpl'}) >> return args >> >> if __name__ == "__main__": >> Session = sessionmaker(bind=engine) >> session = Session() >> academic_sessions = session.query(AcademicSession).all() >> print(academic_sessions) >> course_sets = session.query(CourseSet).all() >> print(course_sets) >> >> >> >> On 27 sep, 23:55, Michael Bayer <mike...@zzzcomputing.com> wrote: >>> On Sep 27, 2010, at 5:10 PM, Julien Iguchi-Cartigny wrote: >>> >>>> But How can i do ? It seems i need to define the table in >>>> AsbtractContainer but every time I've an error about already defined >>>> column. >>> >>> Your original setup seems as though you'd like both CourseSet and >>> CanonicalCourse to be mapped to the same table using single table >>> inheritance. Therefore they both must extend a class that is mapped to >>> the target table. So in this case you'd like AbstractContainer to be >>> mapped, meaning the "Base" superclass should be moved from CourseSet and >>> CanonicalCourse onto AbstractContainer. >>> >>> You can then query for AbstractContainer subclasses using >>> session.query(AbstractContainer). >>> >>> >>> >>> >>> >>>> Cheers, >>> >>>> Julien. >>> >>>> On Mon, Sep 27, 2010 at 10:30 PM, Michael Bayer >>>> <mike...@zzzcomputing.com> wrote: >>> >>>>> On Sep 27, 2010, at 4:21 PM, Julien Iguchi-Cartigny wrote: >>> >>>>>> Thank you Michael. This solves the problem and... shows a new one. >>> >>>>>> So this is my update CourseSet >>> >>>>>> class CourseSet(Base,AbstractContainer): >>> >>>>>> �...@classproperty >>>>>> def __mapper_args__(self): >>>>>> args = dict() >>>>>> args.update(AbstractContainer.__mapper_args__) >>>>>> args.update({'polymorphic_identity': >>>>>> 'org.sakaiproject.coursemanagement.impl.CourseSetCmImpl'}) >>>>>> return args >>> >>>>>> Because there is several discriminant values, I need to create other >>>>>> ones: >>> >>>>>> class CanonicalCourse(Base,AbstractContainer): >>> >>>>>> �...@classproperty >>>>>> def __mapper_args__(self): >>>>>> args = dict() >>>>>> args.update(AbstractContainer.__mapper_args__) >>>>>> args.update({'polymorphic_identity': >>>>>> 'org.sakaiproject.coursemanagement.impl.CanonicalCourseCmImpl'}) >>>>>> return args >>> >>>>>> But this last one will fail, i've the following error message: >>> >>>>>> sqlalchemy.exc.InvalidRequestError: Table 'CM_MEMBER_CONTAINER_T' is >>>>>> already defined for this MetaData instance. Specify >>>>>> 'useexisting=True' to redefine options and columns on an existing >>>>>> Table object. >>> >>>>>> I could use useexisting=True but i don't know if it's the right >>>>>> solution. Any ideas ? >>> >>>>> that has to do with a Table() statement, or alternatively how you are >>>>> configuring __table_name__, neither of which are indicated here, so you >>>>> need to ensure that distinct table names are used whenever a table name >>>>> is declared. >>> >>>>>> Cheers, >>> >>>>>> Julien. >>> >>>>>> On Mon, Sep 27, 2010 at 1:02 AM, Michael Bayer >>>>>> <mike...@zzzcomputing.com> wrote: >>> >>>>>>> On Sep 26, 2010, at 6:38 PM, Julien Iguchi-Cartigny wrote: >>> >>>>>>>> Hi, >>> >>>>>>>> I'm trying to use polymorphic_on with several inheritances: >>> >>>>>>>> engine = create_engine( >>>>>>>> >>>>>>>> 'mysql://xxx:y...@localhost:3306/zzz?charset=utf8&use_unicode=0', >>>>>>>> pool_recycle=3600, echo=True) >>> >>>>>>>> Base = declarative_base() >>> >>>>>>>> class AbstractPersistent(object): >>>>>>>> version = Column('VERSION', Integer) >>>>>>>> last_modified_by = Column('LAST_MODIFIED_BY', String(255)) >>>>>>>> last_modified_date = Column('LAST_MODIFIED_DATE', Date) >>>>>>>> created_by = Column('CREATED_BY', String(255)) >>>>>>>> created_date = Column('CREATED_DATE', Date) >>> >>>>>>>> class AbstractNamed(AbstractPersistent): >>>>>>>> eid = Column('ENTERPRISE_ID', String(255)) >>>>>>>> title = Column('TITLE', String(255)) >>>>>>>> description = Column('DESCRIPTION', String(255)) >>> >>>>>>>> class AbstractContainer(AbstractNamed): >>>>>>>> __tablename__ = 'CM_MEMBER_CONTAINER_T' >>>>>>>> id = Column('MEMBER_CONTAINER_ID',Integer,primary_key=True) >>>>>>>> discriminator = Column('CLASS_DISCR', String(100)) >>>>>>>> __mapper_args__ = {'polymorphic_on': discriminator } >>> >>>>>>>> class CourseSet(Base,AbstractContainer): >>>>>>>> __mapper_args__ = {'polymorphic_identity': >>>>>>>> 'org.sakaiproject.coursemanagement.impl.CourseSetCmImpl'} >>> >>>>>>> AbstractContainer is not mapped, its a mixin, so its __mapper_args__ >>>>>>> are not used until a subclass of Base is invoked, which starts up a >>>>>>> declarative mapping. Your only mapped class then is CourseSet, which >>>>>>> has its own __mapper_args__ , that override those of AbstractContainer >>>>>>> - they are ignored. >>> >>>>>>> To combine __mapper_args__ from a mapped class with those of a mixin, >>>>>>> see the example >>>>>>> athttp://www.sqlalchemy.org/docs/orm/extensions/declarative.html?highli.... >>>>>>> It uses __table_args__ but the same concept of creating a full >>>>>>> dictionary of arguments applies for __mapper_args__ as well. >>> >>>>>>> -- >>>>>>> You received this message because you are subscribed to the Google >>>>>>> Groups "sqlalchemy" group. >>>>>>> To post to this group, send email to sqlalch...@googlegroups.com. >>>>>>> To unsubscribe from this group, send email to >>>>>>> sqlalchemy+unsubscr...@googlegroups.com. >>>>>>> For more options, visit this group >>>>>>> athttp://groups.google.com/group/sqlalchemy?hl=en. >>> >>>>>> -- >>>>>> "Trouble-a-cat limited" >>> >>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "sqlalchemy" group. >>>>>> To post to this group, send email to sqlalch...@googlegroups.com. >>>>>> To unsubscribe from this group, send email to >>>>>> sqlalchemy+unsubscr...@googlegroups.com. >>>>>> For more options, visit this group >>>>>> athttp://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 sqlalch...@googlegroups.com. >>>>> To unsubscribe from this group, send email to >>>>> sqlalchemy+unsubscr...@googlegroups.com. >>>>> For more options, visit this group >>>>> athttp://groups.google.com/group/sqlalchemy?hl=en. >>> >>>> -- >>>> "Trouble-a-cat limited" >>> >>>> -- >>>> You received this message because you are subscribed to the Google Groups >>>> "sqlalchemy" group. >>>> To post to this group, send email to sqlalch...@googlegroups.com. >>>> To unsubscribe from this group, send email to >>>> sqlalchemy+unsubscr...@googlegroups.com. >>>> For more options, visit this group >>>> athttp://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 sqlalch...@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 sqlalch...@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. > > -- "Trouble-a-cat limited" -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalch...@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.