sqlalchemy:当viewonly = True

时间:2019-11-19 16:09:59

标签: python sqlite sqlalchemy

我以简单的多对多关系建立了以下模型:

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)

0 个答案:

没有答案