Great thanks !

There is something I still doesn't understand with automap_base : some 
relationships are created only after the first query call (which takes much 
more time to terminate).

For instance :

>>> from dbaccess import *                # import engine, models, etc.
>>> Dispositif.hardware_collection.attr   # doesn't exist yet
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File 
"/usr/local/lib/python2.7/dist-packages/sqlalchemy/ext/associationproxy.py", 
line 204, in attr
    return (self.local_attr, self.remote_attr)
  File 
"/usr/local/lib/python2.7/dist-packages/sqlalchemy/ext/associationproxy.py", 
line 184, in local_attr
    return getattr(self.owning_class, self.target_collection)
AttributeError: type object 'Dispositif' has no attribute 
'disp_hdw_collection'
>>> dir(Dispositif)                       # there is no 
'disp_hdw_collection', but 'hardware_collection' exists (seems because I 
define it explicitely)
[..., 'classes', 'hardware_collection', 'id', 'metadata', 'prepare']
>>> session = Session()                   # create the first session
>>> l = session.query(Dispositif).all()   # first query call, takes about 2s
>>> Dispositif.hardware_collection.attr   # now exists...
(<sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x148edb0>, <
sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x12f2f90>)
>>> dir(Dispositif)                       # many news relationships and 
collections appear here
[..., 'classes', 'disp_hdw_collection', 'hardware_collection', 'id', 
'metadata', 'prepare', <some_more_collections...>]


Le lundi 31 août 2015 16:33:52 UTC+3, Michael Bayer a écrit :
>
>
>
> On 8/31/15 8:23 AM, [email protected] <javascript:> wrote:
>
>
> Thank you very much.
>
> Le lundi 31 août 2015 06:17:37 UTC+3, Michael Bayer a écrit : 
>
>
>
> On 8/29/15 2:27 PM, [email protected] wrote:
>
> Thanks for the reply.
>
> Le vendredi 28 août 2015 18:52:37 UTC+3, Michael Bayer a écrit : 
>
>
>
> On 8/28/15 3:51 AM, [email protected] wrote:
>
> Another question is why sqlalchemy produce two queries to get hardwares 
> collections from a dispositif :
>
>
> >>> some_disp.hardwares
> 2015-08-28 10:36:41,722 INFO sqlalchemy.engine.base.Engine SELECT disp_hdw
> .iddispositif AS disp_hdw_iddispositif, disp_hdw.idhardware AS 
> disp_hdw_idhardware, disp_hdw.instance AS disp_hdw_instance
> FROM disp_hdw
> WHERE %s = disp_hdw.iddispositif
> 2015-08-28 10:36:41,725 INFO sqlalchemy.engine.base.Engine (2721L,)
> 2015-08-28 10:36:41,768 INFO sqlalchemy.engine.base.Engine SELECT hardware
> .hdw_type AS hardware_hdw_type, hardware.id AS hardware_id, hardware.idbox 
> AS hardware_idbox
> FROM hardware
> WHERE hardware.id = %s
> 2015-08-28 10:36:41,772 INFO sqlalchemy.engine.base.Engine (268L,)
>
>
> There's no context given here, but that would indicate that the 
> "some_disp" instance has been expired.  When you .commit() a session, all 
> objects are expired by default.  This is so that if, when you next operate 
> on the objects, some other transaction has deleted that row, the session 
> can let you know that you're working on stale data.   See the session docs 
> for options on how to control this behavior.
>
>  
> Here the context, all in the same session :
>
> >>> from dbaccess import *    # import engine, Base and tables objects
> >>> from sqlalchemy.orm.session import sessionmaker
> >>> Session = sessionmaker(bind=engine)
> >>> session = Session()
> >>> l = session.query(Dispositif).all()
> >>> some_disp = l[-2]
> >>> engine.echo = True
> >>> some_disp.hardwares
> 2015-08-29 20:34:30,972 INFO sqlalchemy.engine.base.Engine SELECT disp_hdw
> .iddispositif AS disp_hdw_iddispositif, disp_hdw.idhardware AS 
> disp_hdw_idhardware, disp_hdw.instance AS disp_hdw_instance
> FROM disp_hdw
> WHERE %s = disp_hdw.iddispositif
> 2015-08-29 20:34:30,975 INFO sqlalchemy.engine.base.Engine (2721L,)
> 2015-08-29 20:34:31,018 INFO sqlalchemy.engine.base.Engine SELECT hardware
> .hdw_type AS hardware_hdw_type, hardware.id AS hardware_id, hardware.idbox 
> AS hardware_idbox
> FROM hardware
> WHERE hardware.id = %s
> 2015-08-29 20:34:31,022 INFO sqlalchemy.engine.base.Engine (268L,)
>
>
> oh.   Well this is association proxy, which means it needs to load two 
> separate relationships, so that is two SELECT statements with default 
> loader strategy.
>
>
> OK.
>
> In fact, *hardwares* can be retrieved in one query.
>
> instead of somewhat like :
>
> SELECT hardware.hdw_type AS hardware_hdw_type, hardware.id AS hardware_id, 
> hardware.idbox AS hardware_idbox
> FROM hardware
> JOIN disp_hdw ON hardware.id = disp_hdw.idhardware
> WHERE disp_hdw.iddispositif = %s
>
>
> sure thing, use joined eager loading:
>
> http://docs.sqlalchemy.org/en/rel_1_0/orm/loading_relationships.html
>
>
> If I try :
> >>> x = db.query(Dispositif).options(joinedload(Dispositif.
> hardware_collection)).get(2721)
>
> I got an error : sqlalchemy.exc.ArgumentError: mapper option expects 
> string key or list of attributes.
>
>
> if 'hardware_collection' is the association proxy, right now you can't 
> pass it directly like that;  you can use the helper "attr" with 
> joinedload_all:
>
>
>     query.options(joinedload_all(*Dispostif.hardware_collection.attr))
>
> or use the actual relationships:
>
>     
> quey.options(joinedload(Dispotif.attribute_a).joinedload(DispToHardware.attribute_b))
>
>
>
>
>
>
> But it's still possible to "preload" the association part by using :
> >>> x = db.query(Dispositif).options(joinedload(Dispositif.
> disp_hdw_collection)).get(2721)
>
> So calling x.hardware_collection after that produce only one query.
>
> Is there a better way to do ?
>
> Le vendredi 28 août 2015 10:20:55 UTC+3, [email protected] a écrit :
>
> Hello, 
>
> I want to use assocation proxy pattern 
> <http://docs.sqlalchemy.org/en/latest/orm/extensions/associationproxy.html> 
> with automap. I tried this code :
>
>
> Base = automap_base()
>
> class Dispositif(Base):
>     __tablename__ = 'dispositifs'
>     hardwares = association_proxy('disp_hardwares', 'hardware')
>
> class
>
> ...

-- 
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to