Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use SQLAlchemy relationships in ORM event callbacks? Always get None

I have a User model that resembles the following:

class User(db.Model):

    id = db.Column(db.BigInteger, primary_key=True)
    account_id = db.Column(db.BigInteger, db.ForeignKey('account.id'))

    account = db.relationship('Account',
         backref=db.backref('ref_users', cascade='delete'))

    ...

def after_user_write(mapper, connection, target):
    target.account.invalidate_cache()

event.listen(User, 'after_insert', after_user_write)
event.listen(User, 'after_update', after_user_write)
event.listen(User, 'after_delete', after_user_write)

Upon insert after_user_write is being called, but target.account is None (which causes an error) when I expect it to be an Account model. target.account_id is set correctly, it just seems like the relationship reference isn't working as I'd expect.

Any ideas on what's causing this?

like image 261
mmattax Avatar asked Feb 23 '15 22:02

mmattax


People also ask

What is lazy dynamic in SQLAlchemy?

Typically when you query the database, the data get loaded at once; however, lazy parameter allows you to alternate the way they get loaded. lazy = 'select' (or True) lazy = 'dynamic'

What are relationships in SQLAlchemy?

The relationship function is a part of Relationship API of SQLAlchemy ORM package. It provides a relationship between two mapped classes. This corresponds to a parent-child or associative table relationship.

What does SQLAlchemy all () return?

As the documentation says, all() returns the result of the query as a list.

What is lazy loading in SQLAlchemy?

The loading of relationships falls into three categories; lazy loading, eager loading, and no loading. Lazy loading refers to objects are returned from a query without the related objects loaded at first.


1 Answers

The relationship doesn't get set by SQLAlchemy automatically when manually creating objects. If you want to access account in the event callback, set it when you create the User instance:

a1 = Account()
u1 = User(account_id=a1.id)
db.session.add(u1)
db.session.commit()

assert u1.account is None

a2 = Account()
# Here: set the account object, instead of the id
u2 = User(account=a2)
db.session.add(u2)
db.session.commit()

assert u2.account == a2
assert u2.account_id == a2.id
like image 168
keithb Avatar answered Oct 01 '22 23:10

keithb