It seems I confused "concrete" with "joined" inheritance.
What I want to achieve is *joined* inheritance. I've modified the code to reflect that (just removed all concrete references). According to the documentation relationships on joined inheritance are inherited, but I still get an error saying it doesn't recognize super_user as a child of user. On Sunday, August 21, 2016 at 6:37:19 AM UTC+3, Mike Bayer wrote: > > > > On 08/20/2016 08:27 PM, Tom Kedem wrote: > > I suppose I could have a discriminator value for "function type", but I > > have no use for it now (so yeah, the base class is a single column one). > > > > It's a simplified model. The real use-case is as such - the base class > > is "function" and the inheriting classes are all sorts of functions (all > > concrete classes). They all have a collection of "arguments" (many to > > many), which I define in the base class - since the "arguments" can only > > point to a single table. > > > > Maybe it's not the best mapping, I'm open for suggestions. But is there > > anything wrong in my configuration or understanding? > > Two things do not make sense, in terms of the use of ConcreteBase and > "concrete=True". > > One is: > > > id = Column(Integer, ForeignKey(User.id), primary_key=True) > > on SuperUser. > > The other is: > > class UserKeyword(Base): > __tablename__ = 'user_keyword' > user_id = Column(Integer, ForeignKey('user.id'), primary_key=True) > > > both of these imply that the fields of a SuperUser object are stored in > the "super_user" table *and* the "user" table. > > Also, when you say "I suppose I could have a discriminator..." in > response to the question, "did you mean for this to be joined > inheritance?", that suggests you might be under the impression that > "don't have a discriminator" means you must use "concrete inheritance", > which is not true. A "discriminator" is not necessary for any style > of inheritance, as long as you don't need to load objects polymorphically. > > Same question as before, more specifically. When you load a row from > "super_user" in order to get a SuperUser object, should the ORM also be > loading a row from "user" that matches up to it? Or can you get every > possible field in a SuperUser from the "super_user" table alone without > ever looking at "user"? If the former, that would be joined > inheritance. that's what this looks like. > > > > > > > > > > > > > On Saturday, August 20, 2016 at 10:44:24 PM UTC+3, Mike Bayer wrote: > > > > This doesn't look like a concrete mapping, you have a foreign key > > from SuperUser to User. Are you sure this isn't supposed to be an > > ordinary joined inheritance model ? > > > > On Saturday, August 20, 2016, Tom Kedem <tomk...@gmail.com > > <javascript:>> wrote: > > > > I have the following setup (attached python file). > > I'm using an inheritance hierarchy without a discriminator > > field, deriving from AbstractBase. > > I want to be able to use the "keywords" attribute in the > > "SuperUser" class, and from the documentation I understand I > > need to redefine it, however that doesn't seem to work. > > I assume I could manually use a primary join there (as the error > > indicates), but as I understand that's exactly what > > "AbstractBase" class should handle... > > > > -- > > 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+...@googlegroups.com > <javascript:>. > > To post to this group, send email to sqlal...@googlegroups.com > <javascript:>. > > Visit this group at https://groups.google.com/group/sqlalchemy > > <https://groups.google.com/group/sqlalchemy>. > > For more options, visit https://groups.google.com/d/optout > > <https://groups.google.com/d/optout>. > > > > -- > > 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+...@googlegroups.com <javascript:> > > <mailto:sqlalchemy+unsubscr...@googlegroups.com <javascript:>>. > > To post to this group, send email to sqlal...@googlegroups.com > <javascript:> > > <mailto:sqlal...@googlegroups.com <javascript:>>. > > Visit this group at https://groups.google.com/group/sqlalchemy. > > For more options, visit https://groups.google.com/d/optout. > -- 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 post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
from sqlalchemy import ForeignKey from sqlalchemy import Integer from sqlalchemy import Column from sqlalchemy import String from sqlalchemy import create_engine from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship, backref from sqlalchemy.orm import sessionmaker Base = declarative_base() # Inheritance without discriminator class User(Base): __tablename__ = 'user' id = Column(Integer, primary_key=True) keywords = association_proxy('user_keywords', 'keyword') __mapper_args__ = {'polymorphic_identity': 'user'} class UserKeyword(Base): __tablename__ = 'user_keyword' user_id = Column(Integer, ForeignKey('user.id'), primary_key=True) keyword_id = Column(Integer, ForeignKey('keyword.id'), primary_key=True) special_key = Column(String(50)) user = relationship(User, backref=backref("user_keywords", cascade="all, delete-orphan")) keyword = relationship("Keyword") def __init__(self, keyword=None, user=None, special_key=None): self.user = user self.keyword = keyword self.special_key = special_key class Keyword(Base): __tablename__ = 'keyword' id = Column(Integer, primary_key=True) keyword = Column('keyword', String(64)) def __init__(self, keyword): self.keyword = keyword def __repr__(self): return 'Keyword(%s)' % repr(self.keyword) class SuperUser(User): __tablename__ = 'super_user' id = Column(Integer, ForeignKey(User.id), primary_key=True) role = Column(String(64)) __mapper_args__ = {'polymorphic_identity': 'super_user'} # ???? #user_keywords = relationship(UserKeyword) #keywords = association_proxy('user_keywords', 'keyword') engine = create_engine('sqlite:///:memory:', echo=False) Base.metadata.create_all(engine) Session = sessionmaker(bind=engine) session = Session() user = SuperUser() for kw in (Keyword('new_from_blammo'), Keyword('its_big')): user.keywords.append(kw) session.add(user) session.commit()