Thank you so much for your guidance here. I'm going to give this a shot! On Tuesday, March 3, 2020 at 2:00:34 PM UTC-8, Mike Bayer wrote: > > Here's a workaround that tries to adjust for AbstractConcreteBase. The > issue is that ABC does not actually create a "with_polymorphic" selectable > that includes subclass columns, it maps the base class directly to the full > selectable so all those extra columns get mapped. This can probably be > improved, and this issue shouldn't be present with the ConcreteBase > class. By limiting the properties on the local mapper and setting a > separate selectable for the load, both issues are solved, however I haven't > tested this robustly. If it works very well for you we can make this a new > feature of ABC, however there would need to be logic to figure out the > correct "include_properties": > > 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"], > } > > @classmethod > def __declare_last__(cls): > cls.__mapper__.with_polymorphic = ("*", cls.__mapper__.local_table) > > > > On Tue, Mar 3, 2020, at 4:38 PM, Mike Bayer wrote: > > > 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) > <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 sqlal...@googlegroups.com <javascript:>. > 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 sqlal...@googlegroups.com <javascript:>. > To view this discussion on the web visit > https://groups.google.com/d/msgid/sqlalchemy/5707a8c9-815e-4cd1-aa73-66eaba2a6245%40www.fastmail.com > > <https://groups.google.com/d/msgid/sqlalchemy/5707a8c9-815e-4cd1-aa73-66eaba2a6245%40www.fastmail.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/b024aef8-71b9-4fa3-a4ad-b9f9eb78ee11%40googlegroups.com.