Hi Michael, thank you for your quick response!
Yeah, it seems that I got confused about the "load_only" method - it
doesn't load at all. I've tried to put together an easier example to show
the problem. It seems that it is related to the joinedload.
import sqlalchemy.orm
import sqlalchemy.inspection
entity = model.session.query(
model.Asset
).options(
sqlalchemy.orm.joinedload(
'parent'
)
).first()
state = sqlalchemy.inspection.inspect(entity.parent)
for attribute in state.attrs:
is_loaded = (
attribute.loaded_value is not
sqlalchemy.orm.base.NO_VALUE
)
if is_loaded:
print attribute.key
And if I omit it, it load s fine. Here is a simplified version of my model:
class Context(Base):
'''Represent a context.'''
context_type = Column(Unicode(32), nullable=False)
__mapper_args__ = {
'polymorphic_on': context_type,
'polymorphic_identity': 'context'
}
@declared_attr
def __tablename__(cls):
return 'context'
name = Column(Unicode(255), default=u'', nullable=False)
@declared_attr
def id(cls):
return Column(CHAR(36), primary_key=True, default=lambda: str(uuid
()))
@classmethod
def __declare_last__(cls):
'''Return link expression query.'''
# Import this module.
from . import context
context = 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 = column_property(
sqlalchemy.select(
[context.c.name + ' ' + context.c.context_type],
from_obj=[context]
).where(
context.c.id == cls.id
).label('link')
)
class Task(Context):
'''Represent a task.'''
@declared_attr
def __tablename__(cls):
return 'task'
@declared_attr
def __table_args__(cls):
return {
'mysql_engine': 'InnoDB',
'mysql_charset': 'utf8'
}
taskid = Column(
types.CHAR(36),
ForeignKey('context.id'),
primary_key=True
)
__mapper_args__ = {
'polymorphic_identity': 'task'
}
class Asset(Base):
'''Represent an Asset.'''
@declared_attr
def __tablename__(cls):
return 'asset'
@declared_attr
def __table_args__(cls):
return {
'mysql_engine': 'InnoDB',
'mysql_charset': 'utf8'
}
context_id = sqlalchemy.Column(
sqlalchemy.CHAR(36), sqlalchemy.ForeignKey('context.id')
)
parent = relationship('Context', backref=backref('assets'))
I hope this example makes more sense. Can you see any obvious problems with
my approach and why it wouldn't work?
If I add the link as a declared_attr instead it does work:
@declared_attr
def link(cls):
return column_property(cls.name + ' ' + cls.context_type)
However, my real-life use-case link is more complicated and I need to do
imports that would cause circular import errors if I used declared_attr.
Best regards,
Mattias L
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.
>
> import sqlalchemy.orm
> import sqlalchemy.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)
> for attribute in state.attrs:
> is_loaded = (
> attribute.loaded_value is not
> sqlalchemy.orm.base.NO_VALUE
> )
> if is_loaded:
> print attribute.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. 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:
>
>
> class Context(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
> def id(cls):
> return Column(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')
> )
>
> class Task(Context):
> '''Represent a task.'''
>
> taskid = Column(
> types.CHAR(36),
> ForeignKey('context.id'),
> primary_key=True
> )
>
> __mapper_args__ = {
> 'polymorphic_identity': 'task'
> }
>
>
> class Asset(Base):
> '''Represent an Asset.'''
>
> context_id = sqlalchemy.Column(
> sqlalchemy.CHAR(36), sqlalchemy.ForeignKey('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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.