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()

Reply via email to