0

I am writing a simple serializer for SQLAlchemy instances into Python dictionaries and am trying to serialize only objects that were eagerly loaded, but excluding objects that were not. More specifically, I am trying to check the load options of a relationship of a SQLAlchemy object retrieved from a query with custom load options. For e.g.

class Item(db.Model):
    ...
    field = db.relationship('Field', lazy='raise')

item = session.query(Item).options([joinedload(Item.field)]).first()

Now I expect the Item.field relationship to have a lazy='joined' because I overrode the load options at query time, but when I check in item._sa_instance_state.mapper.relationships.get('field').lazy, it is still a 'raise'.

In other words, it seems like SQLAlchemy's query load options is converted into SQL but does not affect the instance's state's load options at all.

  1. I have considered the use of item._sa_instance_state.unloaded as an indicator of whether or not something has been joinloaded. If it was joinloaded, then the field will not be in item._sa_instance_state.unloaded. Is this correct?
  2. If something has been noload, raiseload or select, would they ever not be in item._sa_instance_state.unloaded before being accessed?

Could someone please enlighten me if there is a better way of detecting the load options of an instance after querying please?

Jay Chia
  • 1
  • 1
  • 2
    Hi Jay, have you tried the approach suggested here? https://stackoverflow.com/a/25011704/3794660 – fabio.sussetto Feb 13 '19 at 23:37
  • I would not recommend accessing attributes like `item._sa_instance_state` since they'are "internal use", see https://stackoverflow.com/a/1301369/5781248 ; That mapper attribute is probably something that is not instance specific. If the lazy option for the relationship changed because of joinedload, then all the later queries would be affected which would probably be not so useful. – J.J. Hakala Feb 14 '19 at 02:03
  • Here're yet another examples of using inspection: https://stackoverflow.com/a/50330608/2681632. As @J.J.Hakala points out, don't go for `_sa_instance_state` directly, but use the inspection tools provided by SQLA. – Ilja Everilä Feb 14 '19 at 06:00
  • Got it! I'll make sure to use `inspect` instead of accessing the private `_sa_instance_state`. I have tried using `InstanceState.unloaded` - am I right to say that if I never access any of the fields in `InstanceState.unloaded` then I will never be making any N+1 (lazy loading) queries? Thanks for the comments! – Jay Chia Feb 14 '19 at 18:30

0 Answers0