如何将SQLAlchemy模型对象转换为纯python对象

时间:2017-11-02 09:12:14

标签: python sqlalchemy

我有User(db.Model)和Photo(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。希望很清楚

1 个答案:

答案 0 :(得分:2)

有些东西让我觉得你没有正确使用你的sqlalchemy模型。为什么,而不是从会话中分离并使用您的关系(使用相同用户的多个元组?)进行奇怪的事情,您是否可以通过使用SQLalchemy的机制来为每个用户创建照片列表?

如果你有用户和照片之间的关系,你可以:

  • 将关系加载策略更改为默认值(完全删除lazy属性或将其设置为'select'),然后为用户查询数据库:

    users = db.session.query(User).all()
    

    ...并以db对象列表的形式访问用户的照片。

    user.photos # photos is a list of all user's photos
    
  • lazy='dynamic'您可以通过相同的方式覆盖所有用户,但现在照片也是一个查询(请参阅:dynamic relationships):

      

    启用大型集合管理的关键功能是所谓的“动态”关系。这是一种可选的relationship()形式,它在访问时返回一个Query对象来代替集合

    ...与每个查询一样,您可以使用其API(filter()first()all()来获取所有照片。