如何解决我可以在SQLAlchemy中将相同的对象两次附加到InstrumentedList吗?
| 我在sqlAlchemy 0.6.6中有一个非常简单的N:M关系。我有一个类“ attractLoop”,其中可以包含一堆媒体(图像或视频)。我需要有一个列表,其中同一媒体(可以说是图片)可以附加两次。关系如下: 媒体是具有图像和视频将共享的大多数属性的基类。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))
_type = Column(\"type\",String(50))
_size = Column(\"size\",Integer)
_lastModified = Column(\"last_modified\",DateTime,key=\"lastModified\")
_url = Column(\"url\",String(512))
_thumbnailFile = Column(\"thumbnail_file\",String(512),key=\"thumbnailFile\")
_md5Hash = Column(\"md5_hash\",LargeBinary(32),key=\"md5Hash\")
然后将要使用这些“媒体”东西的班级:
class TestsqlAlchemyList(BaseClass.BaseClass,declarativeBase):
__tablename__ = \"tests\"
_mediaItems = relationship(\"BaseMedia\",secondary=intermediate_test_to_media,primaryjoin=\"tests.c.id == intermediate_test_to_media.c.testId\",secondaryjoin=\"base_media.c.id == intermediate_test_to_media.c.baseMediaId\",collection_class=list,uselist=True
)
def __init__(self):
super(TestsqlAlchemyList,self).__init__()
self.mediaItems = list()
def getMediaItems(self):
return self._mediaItems
def setMediaItems(self,mediaItems):
if mediaItems:
self._mediaItems = mediaItems
else:
self._mediaItems = list()
def addMediaItem(self,mediaItem):
self.mediaItems.append(mediaItem)
#log.debug(\"::addMediaItem > Added media item %s to %s. Now length is %d (contains: %s)\" % (mediaItem.id,self.id,len(self.mediaItems),list(item.id for item in self.mediaItems)))
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))
和中间类链接两个表:
intermediate_test_to_media = Table(
\"intermediate_test_to_media\",Database.Base.Metadata,Column(\"id\",Integer,primary_key=True),Column(\"test_id\",ForeignKey(\"tests.id\"),key=\"testId\"),Column(\"base_media_id\",ForeignKey(\"base_media.id\"),key=\"baseMediaId\")
)
当我将同一个Media对象(实例)两次附加到该TestsqlAlchemyList的一个实例时,它正确地附加了两个,但是当我从数据库中检索TestsqlAlchemyList实例时,我只能得到一个。它似乎表现得更像一套。
中间表正确地包含了所有信息,因此插入似乎工作正常。当我没有从中插入所有项目时尝试从数据库加载列表时。
MysqL> SELECT * FROM intermediate_test_to_media;
+----+---------+---------------+
| id | test_id | base_media_id |
+----+---------+---------------+
| 1 | 1 | 1 |
| 2 | 1 | 1 |
| 3 | 1 | 2 |
| 4 | 1 | 2 |
| 5 | 1 | 1 |
| 6 | 1 | 1 |
| 7 | 2 | 1 |
| 8 | 2 | 1 |
| 9 | 2 | 1 |
| 10 | 2 | 2 |
| 11 | 2 | 1 |
| 12 | 2 | 1 |
如您所见,id = 1的\“ test \”实例应该具有媒体[1、1,2,1,1]。好吧,不是。当我从数据库加载时,它只有媒体[1、2]
我试图在关系中设置任何可能会闻到列表的参数... uselist,collection_class = list ...没什么...
您将看到这些类从BaseClass继承。那只是一个实际上未映射到任何表的类,但包含一个数字字段(\“ id \”),它将作为每个类的主键,以及一堆对其余部分有用的其他方法我系统中的类(toJSON,toXML ...)。以防万一,我附上摘录:
class BaseClass(object):
_id = Column(\"id\",primary_key=True,key=\"id\")
def __hash__(self):
return int(self.id)
def setId(self,id):
try:
self._id = int(id)
except TypeError:
self._id = None
def getId(self):
return self._id
@declared_attr
def id(cls):
return synonym(\'_id\',descriptor=property(cls.getId,cls.setId))
如果有人可以推动我,我将不胜感激。谢谢。很抱歉,我的帖子太多了。我真的不知道该如何更好地解释。
解决方法
我认为您想要的是在文档中被描述为“多对多关系中的其他字段”。而不是在吸引环和媒体之间为每个\“ link \”在数据库中存储唯一行,您将存储单个关联并指定(作为链接对象模型的一部分)被引用多少次和/或在其中进行多次引用。媒体应出现在最终列表中的位置。这是与您开始时不同的范例,因此肯定需要重新编码,但是我认为它可以解决您的问题。您可能需要使用一个属性来重新定义如何从attactLoop中添加或删除Media。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。