I'm not querying polymorphically. 

Let me restate the problem with more details(my post as done in haste).

With something like the example I gave(completed with what's missing, e.g. 
table names, definition for related table), 

# setup connection
# create a session
session = Session(...)

results = session.query(Concrete2).all()

print(results) # this works, the mappings are there
results[0].start # this works

MyBase.start, MyBase.end # that's weird, the Abstract base also has those 
attributes now

session.expire(results[0])
results[0].start 

Traceback (most recent call last):
  File 
"/home/charles/PycharmProjects/MyProject/env/lib/python3.6/site-packages/IPython/core/interactiveshell.py"
, line 3035, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-14-25b20252b355>", line 1, in <module>
    results[0].start
  File "/home/charles/PycharmProjects/MyProject/my_models.py", line 456, in 
start
    return self.details.start
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/attributes.py", line 237, in 
__get__
    return self.impl.get(instance_state(instance), dict_)
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/attributes.py", line 584, in 
get
    value = self.callable_(state, passive)
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/strategies.py", line 539, in 
_load_for_state
    passive
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/strategies.py", line 575, in 
_get_ident_for_use_get
    for pk in self.mapper.primary_key
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/strategies.py", line 575, in 
<listcomp>
    for pk in self.mapper.primary_key
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/mapper.py", line 2564, in 
_get_state_attr_by_column
    return state.manager[prop.key].impl.get(state, dict_, passive=passive)
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/attributes.py", line 579, in 
get
    value = state._load_expired(state, passive)
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/state.py", line 592, in 
_load_expired
    self.manager.deferred_scalar_loader(self, toload)
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/loading.py", line 713, in 
load_scalar_attributes
    only_load_props=attribute_names)
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/loading.py", line 223, in 
load_on_ident
    return q.one()
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2814, in one
    ret = self.one_or_none()
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2784, in 
one_or_none
    ret = list(self)
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/loading.py", line 90, in 
instances
    util.raise_from_cause(err)
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 203, in 
raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 187, in 
reraise
    raise value
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/loading.py", line 57, in 
instances
    for query_entity in query._entities
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/loading.py", line 57, in 
<listcomp>
    for query_entity in query._entities
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 3700, in 
row_processor
    polymorphic_discriminator=self._polymorphic_discriminator
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/loading.py", line 299, in 
_instance_processor
    mapper._props[k] for k in only_load_props)
  File "/home/charles/PycharmProjects/MyProject
/env/lib/python3.6/site-packages/sqlalchemy/orm/loading.py", line 299, in 
<genexpr>
    mapper._props[k] for k in only_load_props)
KeyError: 'start'


So on refresh, the loading process seems to expect 'start' and 'end' to be 
registered by the mappers(which they would be if they were columns, I 
guess).


Le vendredi 27 octobre 2017 13:36:53 UTC-4, Mike Bayer a écrit :
>
> On Fri, Oct 27, 2017 at 11:57 AM,  <[email protected] <javascript:>> 
> wrote: 
> > My SQLAlchemy version is 1.1.14. 
> > 
> > I'm having difficulty understanding behaviours around a polymorphic 
> > hierarchy. 
> > 
> > I have an AbstractConcreteBase and two subclasses. 
> > 
> > The ACB declares some attributes shared by the two subclasses, and the 
> > subclasses have attributes of their own that are not shared(i.e. they 
> are 
> > not part of the shared identity represented by the ACB). 
> > 
> > class MyBase(AbstractConcreteBase, Base, Mixin): 
> >     shared_id = Column(Integer, 
> default=Sequence("database_shared_id_seq", 
> > start=0, increment=1), primary_key=True) 
> > 
> >     @declared_attr 
> >     def name(self): 
> >         return Column(String(100), nullable=False) 
> > 
> >     @declared_attr 
> >     def foreign_key(self): 
> >         return Column(Integer, ForeignKey("MyOtherTable.id")) 
> > 
> >     ... 
> > 
> > 
> > class Concrete1(MyBase): 
> >     start = Column(Date) 
> >     end = Column(Date) 
> > 
> > 
> > class Concrete2(MyBase): 
> > 
> >     @property 
> >     def start(self): 
> >         return self.details.start 
> > 
> >     @property 
> >     def end(self): 
> >         return self.details.end 
> > 
> >     details = relationship("Concrete2Detail", uselist=False, 
> viewonly=True) 
> > 
> > 
> > As you can see, "start" and "end" are not declared in the ACB and are 
> > implemented differently between the table. I don't want them to be 
> shared by 
> > the subclasses. 
> > 
> > When I query one of the Concretes, the ACB mapper is updated with the 
> > "start" and "end" attributes, and then the Concretes are expected to 
> > implement the attributes on the mapper level(which is not the case for 
> > Concrete2). 
>
> This is a natural effect of using an "abstract" base.   When you try 
> to query polymorphically across Concrete1 and Concrete2, you're asking 
> it to query for the Concrete1.start and end columns.   However it 
> should not in any way be modifying the Concrete2 mapper itself.   I'm 
> not sure without running it what "are expected to implement" means. 
> An error is raised? 
>
>
> > 
> > How can I prevent this from happening? 
> > 
> > -- 
> > 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 [email protected] <javascript:>. 
> > To post to this group, send email to [email protected] 
> <javascript:>. 
> > 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 [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to