Skip to content

SQLAlchemy Inheritance and backrefs #89

@dpwrussell

Description

@dpwrussell

If I define an inherited relationship (joined-table in this case) in SQLAlchemy, the backref is not being properly understood by ColanderAlchemy.

In my contrived example there is Person, which is sub-classed in Gamer. Gamer can have some Scores associated with it.

class Person(Base):
    __tablename__ = 'person'

    satype = Column(String(50))
    __mapper_args__ = {
        'polymorphic_identity': 'person',
        'polymorphic_on': satype
    }

    id = Column(Integer, primary_key=True)
    name = Column(String(128))
    surname = Column(String(128))


class Gamer(Person):
    __tablename__ = 'gamer'

    __mapper_args__ = {
        'polymorphic_identity': 'gamer',
    }

    __colanderalchemy_config__ = {
        'excludes': ['satype']
    }

    id = Column(Integer, ForeignKey('person.id'), primary_key=True)
    high_score = Column(Integer)


class Score(Base):
    __tablename__ = 'score'

    id = Column(Integer, primary_key=True)
    gamer_id = Column(Integer, ForeignKey('gamer.id'))
    gamer = relationship('Gamer', backref='scores')
    value = Column(Integer)

This will serialize a Gamer to this:

{'high_score': <colander.null>,
 'id': '1',
 'name': u'Jayne',
 'surname': u'Cobb'}

Which is not what I was expecting. The scores backref is being ignored.

Redefine Gamer to remove use of inheritance like so:

class Gamer(Base):
    __tablename__ = 'gamer'

    id = Column(Integer, primary_key=True)
    name = Column(String(128))
    surname = Column(String(128))
    high_score = Column(Integer)

and the result is:

{'high_score': <colander.null>,
 'id': '1',
 'name': u'Jayne',
 'scores': [{'gamer_id': '1', 'id': '1', 'value': '1000'},
            {'gamer_id': '1', 'id': '2', 'value': '2000'}],
 'surname': u'Cobb'}

which is exactly what I was expecting.

Just for completeness I also tried redefining score to make use of Person instead of Gamer in its relation. This makes no difference:

class Score(Base):
    __tablename__ = 'score'

    id = Column(Integer, primary_key=True)
    gamer_id = Column(Integer, ForeignKey('person.id'))
    gamer = relationship('Person', backref='scores')
    value = Column(Integer)

Working example: https://gist.github.com/dpwrussell/f465aee4618580614f61

I think this must be a bug as I can't see why that would happen otherwise.

Cheers

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions