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