rocknrollnerd
rocknrollnerd

Reputation: 2634

SQLAlchemy's with_polymorphic ignores discriminator

I'm trying to make a polymorphic loading from a joined inhereted table (I use Flask-Sqlalchemy).

class Sip(db.Model):
    id = db.Column(db.Integer, primety_key=True)
    identity = db.Column(db.String(10))
    __mapper_args__ = {'polymorphic_identity': 'sip', 'polymorphic_on': identity}

class Device(Sip):
    id = db.Column(db.Integer, db.ForeignKey('sip.id', ondelete='CASCADE'), primary_key=True)
    __mapper_args__ = {'polymorphic_identity': 'dev'}

class Line(Sip):
    id = db.Column(db.Integer, db.ForeignKey('sip.id', ondelete='CASCADE'), primary_key=True)
    __mapper_args__ = {'polymorphic_identity': 'line'}

I've got one Device object and one Line object. When I try to make such a query:

Sip.query.with_polymorphic(Device).all()

it returns all the objects

[<myapp.models.Device at 0x45cfc50>, <myapp.models.Line at 0x45cfa90>]

Same situation when I use Line as an argument for with_polymorphic(). Table "sip" contains all required identities, I can check it:

>> Sip.query.with_polymorphic(Device).all()[0].identity
>> u'dev'
>> Sip.query.with_polymorphic(Device).all()[1].identity
>> u'line'

I just can't figure what's going on. Everything's seems to be exactly like doc example. Thanks.

Upvotes: 3

Views: 2326

Answers (1)

van
van

Reputation: 76952

with_polymorphic does not filter objects by type, but only defines columns from which other tables to fetch during the initial query. So, if you do not use with_polymorphic in your query, and would like to get a value for an attribute of Line which is stored in lines table, SA will issue another SQL statement to fetch the attribute from the database.

Enable echo=True in the engine, and you will see the different SQL statements been generated depending on the with_polymorphic usage:

  • no usage: only attributes from the sips table would be loaded during the query
  • with_polymorphic(Device): will load attributes for the devices table as well (using LEFT JOINs)
  • with_polymorphic("*"): will load attributes for all the sub-classes in the same query.

For more on the topic please read Basic Control of Which Tables are Queried.

Upvotes: 5

Related Questions