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.