On Thu, Sep 6, 2018 at 4:21 AM, Tomáš Sandrini <warecz...@gmail.com> wrote:
> Hi,
>
> I am writing a library where I need to hide (for normal usage, since that
> will be 90% use case) the existence of a Parent object,
> basically limiting it just to one property and then set the Parent manually
> within the Child class through this one property.
> An obvious solution to this would be to get the session within the
> constructor and set it from here, but that breaks the ORM philosophy
> and I would like to find something more cleaner.
> So I found the 'init_scalar' ORM event, which is perfectly suited for this
> issue, but unfortunately it doesn't fire at all for me.


the init_scalar event is a strange little event to suit one of the
less appealing things SQLAlchemy has to do, which is to give you an
answer when you access an attribute on an object that has no value.
By "access", we mean reading it, not anything else.  E.g.:

print(Children.parent_id)

The answer SQLAlchemy gives you in modern versions is "None", and
nothing happens to the state of the object.  In older versions, it
used to actually set the attribute's state to None, that is, reading
the attribute had a side effect.    When I fixed the attribute system
to not need that anymore, the events were added in case someone wanted
to customize this, in that i can restore the old behavior.    I doubt
anyone uses this event for anything, though. I'm not even sure why I
wrote all those docs for it (and even an example...) because it seems
kind of strange you'd want to persist a special value only if someone
"read" from it, I guess I was nervous about people upgrading from the
old behavior.     So I think this is a case of docs being misleading.

In this case, if the thing you need to do your thing is a Session, you
can catch exactly when that is available using the
transient_to_pending lifecycle event:
http://docs.sqlalchemy.org/en/latest/orm/session_events.html?highlight=session%20lifecycle#transient-to-pending

this works

@event.listens_for(Session, "transient_to_pending")
def init_parent(session, instance):
    if isinstance(instance, Child):   # or whatever mixin, or call a
method on the class, etc.
        with sess.no_autoflush:
            parent = sess.query(Parent).filter(Parent.name ==
instance.name).one()
            instance.parent = parent









>
> This snippet describes what I am trying to accomplish ->
> https://pastebin.com/GEccd7zu
>
> I will appreciate any kind of help.
>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> ---
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> Visit this group at https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to