我以简单的多对多关系建立了以下模型:
Base = declarative_base()
class Image(Base):
__tablename__ = 'images'
id = Column(Text, primary_key=True)
path = Column(Text)
galleries_assoc = relationship("GalleryImage", back_populates="image")
class GalleryImage(Base):
__tablename__ = 'gallery_images'
gallery_id = Column(Text, ForeignKey('galleries.id'), primary_key=True)
image_id = Column(Text, ForeignKey('images.id'))
sequence = Column(Integer, primary_key=True)
image = relationship("Image", back_populates="galleries_assoc")
gallery = relationship("Gallery", back_populates="images_assoc")
class Gallery(Base):
__tablename__ = 'galleries'
id = Column(Text, primary_key=True)
title = Column(Text)
images_assoc = relationship("GalleryImage", back_populates="gallery")
画廊有很多图像,一个图像可以属于许多画廊。这些图像通过sequence
连接表中的gallery_images
列在图库中排序。插入新图像需要指定sequence
值,因此无法使用secondary
参数简化关系。
此时插入和更新图库和图像可以正常工作,但是访问与图库相关的图像很麻烦,需要使用gallery.images_assoc[0].image.path
之类的语句。因此,我想添加一个额外的关系,该关系可用于从图库中读取图像,例如gallery.images[0].path
等。
我将此关系添加到了Gallery
模型中:
images = relationship("Image", secondary=GalleryImage.__table__, viewonly=True)
这对于从库中读取图像也可以正常工作。但是,由于我已经指定了viewonly=True
,因此我期望sqlalchemy在尝试插入时会警告或引发错误。但是事实并非如此:
>>> g = Gallery(id='g')
>>> g.images = [Image(id='i')]
>>> dbsession.add(g)
>>> dbsession.commit()
如果执行此操作,则画廊和图像将提交到数据库,但未创建连接记录。 (有趣的是,如果我删除了viewonly=True
并尝试了上述操作,则sqlalchemy尝试插入连接记录,并由于IntegrityError
的值而失败,并返回sequence
。)
我误解了viewonly
属性的作用吗?我对文档的阅读表明,这将防止通过这种关系插入新对象。如果我错了,此属性的作用是什么?我该如何执行所需的行为?
(Python:3.7.5,Sqlalchemy:1.3.11,Sqlite:3.28.0)