SQLAlchemy:如何使用ID而不是对象来添加关系?

16

是否可以使用id而非对象向SQLAlchemy关系添加内容?

例如,考虑两个声明性的SQLAlchemy类Review和Artist之间的关系:

class Review(Base):
    artist_id = Column(Integer, ForeignKey('artist.id'))
    artist = relationship(Artist, backref=backref('reviews', order_by=id))
    # etc.

class Artist(Base):
    # etc.

有一个要添加到艺术家的评论ID列表,我似乎需要从该ID查找艺术家,然后将艺术家对象添加到评论中,就像这样:

for review_id in review_ids:
    review = session.query(Review).filter(Review.id==review_id).first()
    artist.reviews.append(review)

我确信跳过查找过程直接添加ID会更有效率,但这种做法可行吗?


1
我能够通过遵循这个答案来完成这个任务。 - akindofyoga
3个回答

9

你最好的选择可能是针对后台表编写一个更新表达式。否则,你实际上无法修改Review,因为你需要查询它(这就是你正在做的事情; 你实际上并没有修改Artist)。

假设Review.id是主键,大致如下:

conn = session.connection()
conn.execute(Review.__table__
                .update()
                .values(artist_id=artist_id)
                .where(Review.id.in_(review_ids))
            )

8
我认为如果您想坚持使用纯ORM解决方案,那么您将不得不接受略微低效的查询模式。@TokenMacGuy提供了一个很好的替代方案。您可以通过将add_reviews()添加到Artist()类来集成该方法。这将增强“标准”的ORM API,因此您可以根据情况使用任何一种方法。
from sqlalchemy.orm.session import object_session

class Artist(Base):
    def add_reviews(self, review_ids):
        sess = object_session(self)
        if isinstance(review_ids, int): review_ids = [review_ids]
        sess.execute(
            Review.__table__
            .update()
            .values(artist_id=self.artist_id)
            .where(Review.id.in_(review_ids))
        )
        sess.refresh(self)

review_ids = [123, 556, 998, 667, 111]
artist.add_reviews(review_ids)
review_id = 333
artist.add_reviews(review_id)

3

我不确定我是否理解了。我猜你想要这样的东西:

reviews = session.query(Review).filter(Review.id.in_(review_ids)).all()

artist.reviews.extend(reviews)

其实这就是我正在做的事情!我写了上面的代码来提供一个更简单的例子。它仍然在每次插入时查找Review对象,而我正试图避免这种情况。不过还是谢谢你的建议。 - Ollie Glass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接