从 dict 加载 sqlalchemy orm 模型

dak*_*kra 5 python sqlalchemy

比方说,我有一个User带有属性的模式idnameemail和关系languages。是否可以User从现有数据创建一个实例,其行为就像我用 查询它一样dbsession.query(User).get(42)?我特别想说的是,我希望能够访问user.languages创建子查询并填充属性。

这是一个代码示例:

我有一堂课User

class User(Base):
    id = Column(Integer, primary_key=True)
    name = Column(String(64))
    email = Column(String(64))

    languages = relationship('Language', secondary='user_languages')
Run Code Online (Sandbox Code Playgroud)

我已经有很多用户存储在我的数据库中。例如,我知道我的数据库中有这个用户:

user_dict = {
    'id': 23,
    'name': 'foo',
    'email': 'foo@bar',
}
Run Code Online (Sandbox Code Playgroud)

所以我拥有除了关系之外的所有属性。现在我想创建一个 sqlalchemyUser实例并在 sqlalchemy 的系统中注册它,以便我可以在languages需要时获得它。

user = User(**user_dict)

# Now I can access the id, name email attributes
assert user.id == 23

# but since sqlalchemy thinks it's a new model it doesn't
# lazy load any relationships
assert len(user.languages) == 0
# I want here that the languages for the user with id 23 appear

# So I want that `user` is the same as when I would have done
user_from_db =  DBSession.query(User).get(23)
assert user == user_from_db
Run Code Online (Sandbox Code Playgroud)

用例是我有一个包含许多复杂关系的大模型,但 90% 的时间我不需要这些数据。所以我只想缓存直接属性以及我需要的其他内容,然后像上面一样从缓存中加载它们,并且能够像我从数据库中查询它一样使用 sqlalchemy 模型。

[编辑:添加了代码示例并重新表述了问题]

[Edit2:添加解决方案]

解决方案

来自 sqlalchemy 邮件列表:

# to make it look like it was freshly loaded from the db
from sqlalchemy.orm.session import make_transient_to_detached
make_transient_to_detached(user)
# merge instance in session without emitting sql
user = DBSession.merge(user, load=False)
Run Code Online (Sandbox Code Playgroud)

sna*_*erb 0

来自 sqlalchemy 邮件列表:

# to make it look like it was freshly loaded from the db
from sqlalchemy.orm.session import make_transient_to_detached
make_transient_to_detached(user)
# merge instance in session without emitting sql
user = DBSession.merge(user, load=False)
Run Code Online (Sandbox Code Playgroud)

这个答案是从问题中提取的