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 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.

Reply via email to