The attributes aren't available from the class that they aren't a part of:

(Pdb) ld = LocationDetail()
(Pdb) hasattr(ld, "starts_at")
False
(Pdb) ld.starts_at
*** AttributeError: Concrete mapped class LocationDetail->LocationDetail does 
not implement attribute 'starts_at' at the instance level. Add this property 
explicitly to mapped class LocationDetail->LocationDetail.

the fact that the attributes are there at all is an artifact of the way 
AbstractConcreteBase works. 

There is a way to exclude these properties from the base, which is to use the 
include_properties collection:

class EventDetail(Base, AbstractConcreteBase):

 uid = Column(Integer, primary_key=True)

 @declared_attr
 def event_id(cls):
 return Column(Integer, ForeignKey(Event.uid))

 @declared_attr
 def event(cls):
 return relationship(Event, back_populates="details")

 __mapper_args__ = {
 "include_properties": ["uid", "event_id", "type"]
 }

However, this means that the querying the base EventDetail doesn't actually 
*load* those properties; when you access them, an additional SQL query has to 
be emitted. Even worse, they are actually in the original SELECT query but they 
aren't assigned to the objects. I don't know why this is, as the more 
well-maintained forms of inheritance (joined and single) don't have any of 
these issues. These can all be considered to be bugs with concrete inheritance 
but I don't have any solution for them right now.

(also make sure you set up back_populates on your mutually-dependent 
relationships)

Since concrete inheritance is documented as being very buggy (see dragon at 
https://docs.sqlalchemy.org/en/13/orm/inheritance.html#concrete-inheritance) I 
would probably just make EventDetail into a non-mapped mixin class and then 
have LocationDetail and SchedulingDetail load from separate relationships. 







On Tue, Mar 3, 2020, at 3:14 PM, Isaac Martin wrote:
> SQLalchemy prescribes a pattern for dealing with polymorphic relationships 
> which are one to many. You can see this pattern here: 
> https://docs.sqlalchemy.org/en/13/orm/extensions/declarative/api.html#sqlalchemy.ext.declarative.AbstractConcreteBase
> 
> After implementing this pattern I was pleased to find that it correctly 
> created my tables for the child classes, did not create a table for the 
> parent class, and successfully loads all children into a single collection on 
> the one side of the one to many. Basically everything I wanted.
> 
> Unfortunately, I quickly came to discover that all child classes had all the 
> fields of all the other child classes. This doesn't happen on the tables, it 
> is only present on the ORM objects after they are loaded. This presents an 
> incredibly poor user experience for the developer. When they inspect these 
> objects they discover a litany of irrelevant fields. Further, tools which 
> visualize the data structure include these fields, making the visualization 
> extremely confusing. For more in depth explanation of my specific 
> implementation you can refer to the stack overflow post: 
> https://stackoverflow.com/questions/60469773/sqlalchemy-polymorphic-pattern-creates-duplicated-columns
> 
> Does anyone know how to prevent SQL alchemy from including fields from sister 
> objects when implementing this pattern?
> 
> 
> 

> --
>  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 view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/7a740ba1-ade8-40fc-914e-85c390e370a8%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/sqlalchemy/7a740ba1-ade8-40fc-914e-85c390e370a8%40googlegroups.com?utm_medium=email&utm_source=footer>.

-- 
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 view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/5707a8c9-815e-4cd1-aa73-66eaba2a6245%40www.fastmail.com.

Reply via email to