Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create ORM object from dict and add to session

Let's say I have a User model with attributes id, name, email and a relationship languages. Is it possible to create a User instance from existing data that behaves like I would have queried it with dbsession.query(User).get(42)? What I mean in particular is that I want that an access to user.languages creates a subquery and populates the attribute.

Here a code example:

I have a class User:

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

    languages = relationship('Language', secondary='user_languages')

I already have a lot of users stored in my DB. And I know that I have, for example, this user in my DB:

user_dict = {
    'id': 23,
    'name': 'foo',
    'email': 'foo@bar',
}

So I have all the attributes but the relations. Now I want to make a sqlalchemy User instance and kind of register it in sqlalchemy's system so I can get the languages if needed.

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

The use-case is that I have a big model with lots of complex relationships but 90% of the time I don't need the data from those. So I only want to cache the direct attributes plus what else I need and then load those from the cache like above and be able to use the sqlalchemy model like I would have queried it from the db.

like image 382
dakra Avatar asked May 31 '26 12:05

dakra


1 Answers

From the sqlalchemy mailing list:

# 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)

This answer was extracted from the question

like image 117
snakecharmerb Avatar answered Jun 03 '26 02:06

snakecharmerb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!