SQLAlchemy: 用id而非对象添加关系?
可以用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而跳过查找过程会更高效,但这样做可以吗?
3 个回答
2
我不太确定我是否理解了。你想要的可能是这样的:
reviews = session.query(Review).filter(Review.id.in_(review_ids)).all()
artist.reviews.extend(reviews)
8
我觉得如果你想坚持使用纯粹的ORM解决方案,你就得接受这种查询方式有点不够高效。
@TokenMacGuy 提供了一个不错的替代方案。你可以通过在 Artist()
类中添加 add_reviews()
方法来整合这个方法。这样一来,你就可以在“标准”的ORM接口和这个新方法之间根据情况选择使用。
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)
9
你最好的办法可能是针对后面的表写一个 update
表达式。否则,你实际上无法修改一个 Review
,因为你必须先查询它(而你现在做的就是这个;你并没有真正修改 Artist
)。
假设 Review.id
是主键,那么大致可以这样写:
conn = session.connection()
conn.execute(Review.__table__
.update()
.values(artist_id=artist_id)
.where(Review.id.in_(review_ids))
)