On 11/03/2015 07:32 AM, Mattias Lagergren wrote:
Hi Michael,
I've been putting together a self-contained example. If you save it to a
file test_model you should be able to run it:
what's the SQL output with echo=True on the engine? is the subquery for
context rendered in the SQL and is it correct?
What happens if you load just a Context object by itself?
the example here isn't exactly "self contained" because it loads data
that's not there. Also there's no need to "import test_model", "cls",
right there is the Context object.
What happens if you run the example using no inheritance at all?
It might be possible that __declare_last__() isn't appropriate here, can
you try just saying "Context.link = column_property()"... right after
you declare Context?
|
importsqlalchemy
importsqlalchemy.orm
importsqlalchemy.inspection
importsqlalchemy.ext.declarative
DATABASE_URL =<database-url>
Base=sqlalchemy.ext.declarative.declarative_base()
classContext(Base):
'''Represent a context.'''
context_type =sqlalchemy.Column(
sqlalchemy.types.Unicode(32),nullable=False
)
__mapper_args__ ={
'polymorphic_on':context_type,
'polymorphic_identity':'context'
}
__tablename__ ='context'
name =sqlalchemy.Column(
sqlalchemy.types.Unicode(255),default=u'',nullable=False
)
id =sqlalchemy.Column(
sqlalchemy.types.CHAR(36),primary_key=True
)
@classmethod
def__declare_last__(cls):
'''Return link expression query.'''
# Import this module.
importtest_model ascontext
context =sqlalchemy.orm.aliased(context.Context.__table__)
# My real use-case is more complicated and involves a lot of joinst to
# other tables, but this example reproduces the issue.
cls.link =sqlalchemy.orm.column_property(
sqlalchemy.select(
[context.c.name +' '+context.c.context_type],
from_obj=[context]
).where(
context.c.id ==cls.id
).label('link')
)
classTask(Context):
'''Represent a task.'''
__tablename__ ='task'
__mapper_args__ ={
'polymorphic_identity':'task'
}
taskid =sqlalchemy.Column(
sqlalchemy.types.CHAR(36),
sqlalchemy.ForeignKey('context.id'),
primary_key=True
)
classAsset(Base):
'''Represent an Asset.'''
__tablename__ ='asset'
assetid =sqlalchemy.Column(
sqlalchemy.types.CHAR(36),primary_key=True
)
context_id =sqlalchemy.Column(
sqlalchemy.CHAR(36),sqlalchemy.ForeignKey('context.id')
)
parent =sqlalchemy.orm.relationship(
'Context'
)
if__name__ =='__main__':
print'Loaded attributes: '
# Create engine.
engine =sqlalchemy.create_engine(
DATABASE_URL
)
Session=sqlalchemy.orm.sessionmaker(bind=engine)
session =Session()
entity =session.query(
Asset
).options(
sqlalchemy.orm.joinedload('parent')
).first()
state =sqlalchemy.inspection.inspect(entity.parent)
forattribute instate.attrs:
is_loaded =(
attribute.loaded_value isnot
sqlalchemy.orm.base.NO_VALUE
)
ifis_loaded:
printattribute.key
|
On Monday, November 2, 2015 at 3:16:07 PM UTC+1, Mattias Lagergren wrote:
Hi,
I'm trying to use load_only and joinedload on a relationship
model.Asset.parent. The parent relation is polymorphic and can be
either Task or Project with the common Base class called Context.
|
importsqlalchemy.orm
importsqlalchemy.inspection
entity =model.session.query(
model.Asset
).options(
sqlalchemy.orm.joinedload('parent').load_only(
'context_type','name','link'
)
).first()
state =sqlalchemy.inspection.inspect(entity.parent)
forattribute instate.attrs:
is_loaded =(
attribute.loaded_value isnot
sqlalchemy.orm.base.NO_VALUE
)
ifis_loaded:
printattribute.key
# Output:
id
taskid
name
context_type
|
The id, name and context_type is from Context. And taskid is primary
key on the taskid and is a foreignkey to the context.id
<http://context.id>. As you can see "name" loads fine but "link"
attribute is not loaded. The "link" column is added as a
column_property to Context using a __declare_last__.
These are simplified versions of the classes:
|
classContext(Base):
'''Represent a context.'''
context_type =Column(Unicode(32),nullable=False)
__mapper_args__ ={
'polymorphic_on':context_type,
'polymorphic_identity':'context'
}
name =Column(Unicode(255),default=u'',nullable=False)
@declared_attr
defid(cls):
returnColumn(CHAR(36),primary_key=True,default=lambda:str(uuid()))
@classmethod
def__declare_last__(cls):
'''Return link expression query.'''
...
cls.link =column_property(
sqlalchemy.type_coerce(
query,LinkTypeDecorator
).label('link')
)
classTask(Context):
'''Represent a task.'''
taskid =Column(
types.CHAR(36),
ForeignKey('context.id <http://context.id>'),
primary_key=True
)
__mapper_args__ ={
'polymorphic_identity':'task'
}
classAsset(Base):
'''Represent an Asset.'''
context_id =sqlalchemy.Column(
sqlalchemy.CHAR(36),sqlalchemy.ForeignKey('context.id
<http://context.id>')
)
parent =relationship('Context',backref=backref('assets'))
|
Can you see if I'm doing something wrong?
--
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
<mailto:sqlalchemy+unsubscr...@googlegroups.com>.
To post to this group, send email to sqlalchemy@googlegroups.com
<mailto:sqlalchemy@googlegroups.com>.
Visit this group at http://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 http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.