Hello everyone... I'm experiencing an strange behavior with an instrumented list...
On one hand, I have a class called "BaseMedia" that is the base type for Images, Videos... On the other hand I have a class "Schedule" that is the base class for "schedulable" things in my system and then I have something called "AttractLoop" that is an Schedulable thing with a list of media (images or videos to be played). All these elements inherit from a class that is not mapped to any specific table called "BaseClass" (where the primary key is). The structure is: BaseClass | BaseMedia / \ Image Video BaseClass | Schedule | AttractLoop The classes are: ============ BaseClass.py (super base class for everything) ====== class BaseClass(object): _id = Column("id", Integer, primary_key=True, key="id") #[ . . . Implementation, getters/setters and other methods . . .] @declared_attr def id(cls): return synonym('_id', descriptor=property(cls.getId, cls.setId)) ===== The BaseMedia, base element for Images, Videos... ======= class BaseMedia(BaseClass.BaseClass, declarativeBase): __tablename__ = "base_media" _polymorphicIdentity = Column("polymorphic_identity", String(20), key="polymorphicIdentity") __mapper_args__ = { 'polymorphic_on': _polymorphicIdentity, 'polymorphic_identity': None } _name = Column("name", String(50)) _md5Hash = Column("md5_hash", LargeBinary(32), key="md5Hash") #[ . . . Implementation, getters/setters and other methods . . .] name = synonym('_name', descriptor=property(getName, setName)) md5Hash = synonym('_md5Hash', descriptor=property(getMd5Hash, setMd5Hash)) ====== The base for every schedulable element =========== class Schedule(BaseClass.BaseClass, declarativeBase): __tablename__ = "schedules" _polymorphicIdentity = Column("polymorphic_identity", String(20), key="polymorphicIdentity") __mapper_args__ = { 'polymorphic_on': _polymorphicIdentity, 'polymorphic_identity': None } _name = Column("name", String(256)) _startDate = Column("start_date", Date, key="startDate") _endDate = Column("end_date", Date, key="endDate") _startTime = Column("start_time", Time, key="startTime") _endTime = Column("end_time", Time, key="endTime") def __init__(self): """Initialize object""" super(Schedule, self).__init__() self.name = "" self.startDate = None self.startTime = None self.endDate = None self.endTime = None #[ . . . Implementation, getters/setters and other methods . . .] name = synonym('_name', descriptor=property(getName, setName)) startDate = synonym('_startDate', descriptor=property(getStartDate, setStartDate)) endDate = synonym('_endDate', descriptor=property(getEndDate, setEndDate)) startTime = synonym('_startTime', descriptor=property(getStartTime, setStartTime)) endTime = synonym('_endTime', descriptor=property(getEndTime, setEndTime)) ====== The attract loop class (child of Schedule) ======= class AttractLoop(Schedule.Schedule): __tablename__ = "attract_loops" __mapper_args__ = { 'polymorphic_identity': 'AttractLoop' } _id = Column("id", Integer, ForeignKey(Schedule.Schedule.id), primary_key=True) _mediaItems = relationship(BaseMedia.BaseMedia, secondary=Tables.intermediate_attract_loop_to_media, order_by=BaseMedia.BaseMedia.name, collection_class=list ) def __init__(self): super(AttractLoop, self).__init__() self.mediaItems = list() def getMediaItems(self): return self._mediaItems def setMediaItems(self, mediaItems): if mediaItems: self._mediaItems = list(mediaItems) else: self._mediaItems = list() def addMediaItem(self, mediaItem): self.mediaItems.append(mediaItem) def addMediaItemById(self, mediaItemId): mediaItem = backlib.media.BaseMediaManager.BaseMediaManager.getById(int(mediaItemId)) if mediaItem: if mediaItem.validityCheck(): self.addMediaItem(mediaItem) else: raise TypeError("Media item with id %s didn't pass the validity check" % mediaItemId) else: raise KeyError("Media Item with id %s not found" % mediaItem) mediaItems = synonym('_mediaItems', descriptor=property(getMediaItems, setMediaItems)) The auxiliary (secondary) table to model the relationship looks like this: intermediate_attract_loop_to_media = Table( "intermediate_attract_loop_to_media", metadata, Column("id", Integer, primary_key=True), Column("attract_loop_id", Integer, ForeignKey("schedules.id"), key="attractLoopId"), Column("base_media_id", Integer, ForeignKey("base_media.id"), key="baseMediaId") ) At a certain point, I generate some canned data (some samples) of AttractLoop, and I append three times the same "media" object (same instance = same numeric id) to the mediaItems list of the sample attractLoop created. Right before saving the sample attractLoop in the database, I can check the length of its "mediaItems" field, and I properly get a length of 3. If I show the ids of the media in that list, I properly get: >> Sample AttractLoop with id 4 has 3 mediaItems ([2L, 2L, 2L]) If I query the intermediate table, it properly shows: +----+-----------------+---------------+ | id | attract_loop_id | base_media_id | +----+-----------------+---------------+ | 1 | 4 | 2 | | 2 | 4 | 2 | | 3 | 4 | 2 | | 4 | 3 | 1 | | 5 | 3 | 1 | | 6 | 3 | 1 | | 7 | 2 | 2 | | 8 | 2 | 2 | | 9 | 2 | 2 | | 10 | 1 | 1 | | 11 | 1 | 1 | | 12 | 1 | 1 | +----+-----------------+---------------+ But if right after merging and flushing that sample I query it again: query = session.query(AttractLoop.AttractLoop) for attractLoop in query: print("Got attract loop %d with %d media thingies (type is %s). Content: %s\n" % (attractLoop.id, len(attractLoop.mediaItems), type(attractLoop.mediaItems), list(mediaThingy.id for mediaThingy in attractLoop.mediaItems))) Got attract loop 1 with 1 media thingies (type is <class 'sqlalchemy.orm.collections.InstrumentedList'>). Content: [1L] Got attract loop 2 with 1 media thingies (type is <class 'sqlalchemy.orm.collections.InstrumentedList'>). Content: [2L] Got attract loop 3 with 1 media thingies (type is <class 'sqlalchemy.orm.collections.InstrumentedList'>). Content: [1L] Got attract loop 4 with 1 media thingies (type is <class 'sqlalchemy.orm.collections.InstrumentedList'>). Content: [2L] And I have no idea of why. Sorry for the huge email, but I wanted to explain the problem in detail, because I have no clue of why this is happening. Thank you in advance -- 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.