On Sep 4, 2014, at 12:28 PM, Ofir Herzas <[email protected]> wrote:

> Thanks Simon,
> I've tried the following:
> 
> session.query(Employee).options(sa.orm.joinedload(Employee.jobs).load_only('id',
>  'first_name')).all()
> 
> which according to the documentation 
> (http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-loading-with-multiple-entities)
>  should work, but it throws an exception (ArgumentError: mapper option 
> expects string key or list of attributes)
> 
> Can you please provide an example?

check your SQLAlchemy version, I cannot reproduce that issue:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Employee(Base):
    __tablename__ = 'employee'

    id = Column(Integer, primary_key=True)
    jobs = relationship("Job")

class Job(Base):
    __tablename__ = 'job'

    id = Column(Integer, primary_key=True)
    employee_id = Column(Integer, ForeignKey('employee.id'))
    first_name = Column(String)

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

session = Session(e)

session.query(Employee).options(joinedload(Employee.jobs).load_only('id', 
'first_name')).all()

output:

SELECT employee.id AS employee_id, job_1.id AS job_1_id, job_1.first_name AS 
job_1_first_name 
FROM employee LEFT OUTER JOIN job AS job_1 ON employee.id = job_1.employee_id



> 
> Please notice that I'm trying to load only some properties of Employee 
> (including one relationship) while this behavior should not be the default 
> behavior (meaning that I don't want the defer the columns at model level)
> 
> 
> On Thursday, September 4, 2014 5:59:21 PM UTC+3, Simon King wrote:
> On Thu, Sep 4, 2014 at 3:28 PM, Ofir Herzas <[email protected]> wrote: 
> > Hi, 
> > I have a model similar to the following: 
> > 
> > class Employee(Base): 
> >     __tablename__ = "t_employee" 
> > 
> >     id = sa.Column(Identifier, sa.Sequence('%s_id_seq' % __tablename__), 
> > primary_key=True, nullable=False) 
> >     first_name = sa.Column(sa.String(30)) 
> >     last_name = sa.Column(sa.String(30)) 
> >     phone_number = sa.Column(sa.String(30)) 
> > 
> >     _jobs = sa.orm.relationship("EmployeeJob", lazy="joined", cascade="all, 
> > delete, delete-orphan") 
> > 
> >     @property 
> >     def name(self): 
> >         return self.first_name + (" " + self.last_name if 
> > len(self.last_name 
> > or "") > 0 else "") 
> > 
> >     @property 
> >     def jobs(self): 
> >         return [item.job_id for item in sorted(self._jobs, 
> > key=attrgetter('id'))] 
> > 
> >     @jobs.setter 
> >     def jobs(self, value): 
> >         self._jobs = [EmployeeJob(job_id=id_) for id_ in to_list(value)] 
> > 
> > class EmployeeJob(Base): 
> >     id = sa.Column(sa.BigInteger, sa.Sequence('%s_id_seq' % __tablename__), 
> > primary_key=True, nullable=False) 
> >     employee_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_employee.id', 
> > ondelete="CASCADE"), nullable=False) 
> >     job_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_job.id', 
> > ondelete="CASCADE"), nullable=False) 
> > 
> > 
> > Now, I'm trying to write a simple query that will fetch all employees with 
> > their jobs. 
> > As I understand, I need to use joinedload so that the list of jobs will be 
> > eagerly loaded but I can't understand how to do it. 
> > 
> > I tried the following: 
> > session.query(Employee.id).options(sa.orm.joinedload(Employee.jobs)) 
> > 
> > but it doesn't work. 
> > 
> > Just to clarify, I want to load some of the columns, not all of them, and 
> > I'm expecting to get the list of jobs for each employee (hopefully like the 
> > getter produces them) 
> > 
> > session.query(Employee) does fetch the required information but it selects 
> > some unneeded columns 
> > 
> > Also, how do I select the name property? 
> > 
> > Thanks, 
> > Ofir 
> > 
> 
> Eager loading means that when you have an instance of Employee, and 
> you access its 'jobs' property, no SQL is emitted because the data is 
> already available. This implies that you have to query for the 
> Employee class, not just one of its columns (otherwise you wouldn't 
> have an instance from which to access the "jobs" property) 
> 
> If you don't want to load all the Employee columns, you can defer them: 
> 
>   
> http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-column-loading
>  
> 
> Hope that helps, 
> 
> Simon 
> 
> -- 
> 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.

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

Reply via email to