我有用户(db.Model)和照片(db.Model),它们之间有一对多的关系,因此用户有很多照片。
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
photos = db.relationship('Photo', backref='user', lazy='dynamic')
def to_json(self):
json = {
'id': self.id,
'photos': [photo.to_json() for photo in self.photos] if self.photos else None,
'name': self.name
}
return json
class Photo(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
name = db.Column(db.String(1024), nullable=False)
def to_json(self):
json = {
'id': self.id,
'user_id': self.user_id,
'name': self.name
}
return json
我的目标是使用单个查询选择所有用户的照片,并使用本机查询:
from sqlalchemy import text
statement = text('SELECT u.*, p.* FROM user u LEFT JOIN photo p ON u.id=p.user_id')
user_photo_query = db.session.query(User, Photo).from_statement(statement)
user_photo_tuples = user_photo_query.all()
users_dict = {}
db.session.expunge_all()
db.session.close()
for u, p in user_photo_tuples:
if not users_dict.get(u.id, None):
u.photos = list()
users_dict.update({u.id: u})
users_dict.get(u.id).photos.append(p)
users = users_dict.values()
return jsonify({'users': [user.to_json() for user in users]})
在这个查询的结果中有一个元组列表(User_240298428,Photo_20394823)。这张照片在这个列表的每一个记录中都是不同的。对于列表的某些记录,用户是相同的。因为我不希望用户和照片对象被绑定到会话中,所以我这样做:
db.session.expunge_all()
db.session.close()
因此,我遍历列表并尝试将所有照片添加到相应的user.photos列表中。
users_dict.get(u.id).photos.append(p)
这里我发现了错误:
父实例不绑定到会话;不能继续执行属性“user”的延迟加载操作。
这是因为用户对象与照片对象的关系:
photos = db.relationship('Photo', backref='user', lazy='dynamic')
我想要的是使用user.photos作为常规列表,而不是作为SQLAlchemy关系。我想将照片添加到用户列表中,而不是以某种方式连接到sqlalchemy。希望这是清楚的
发布于 2017-11-02 01:36:03
有件事让我觉得你没有好好利用你的炼金术模型。为什么你不能脱离会话,用你的关系做一些奇怪的事情(同一个用户的很多元组?),你不能利用SQLalchemy的机制来创建每个用户的照片列表吗?
如果您有用户和照片之间的关系,您可以:
lazy='dynamic'
,您可以以相同的方式访问所有用户,但是现在照片也是一个查询(详细介绍:动态关系):
支持大型集合管理的一个关键特性是所谓的“动态”关系。这是relationship()的一种可选形式,它在访问时返回查询对象而不是集合。...and和每个查询一样,您可以使用它的API (filter()
、first()
,或者在您的例子中是all()
)获取所有照片。
https://stackoverflow.com/questions/47071416
复制相似问题