Search code examples
pythonsqlalchemyorm

SQLAlchemy select specific columns with Table class return


Before start, lets define the table such that:

Base = declarative_base()

class People(Base):
    __tablename__ == 'people'

    idx = Column('idx', Integer, primary_key=True)

    name = column('name', char(50))
    weight = column('weight', char(30))
    height = column('height', char(30))
    hobby = column('hobby', char(30))

With People class(or table? anyway), i know that result = session.scalars(select(People)) Are can access the values like this(Temporarily call this a 'dot access'):

for row in result:
    print(f"{row.name} is the name")
    print(f"weight are... {row.weight}")
    print(f"let me show your {row.hobby}")

But result of result = session.scalars(select(People.name, People.weight, People.hobby)) are can not use the 'dot access'. (The type of rows are Tuple)

And i also using sqlalchemy.orm.Bundle: (select(Bundle("People", People.name, People.weight, People.hobby,)) but this are not works at all. (This also Tuple)

Finally, i really want that result of such querys are Table class! (So that i can use the 'dot access')


Solution

  • You should use scalars() when you are actually returning the whole objects. If you are selecting a couple of columns (as you are doing right here), what you can do is:

    result = session.execute(select(People.name, People.height)).all()
    # here we have an iterator of "Row" objects
    for p in result:
        print(p.name, p.height)
    

    Note the execute statement, instead of scalars.

    If you need to use an expression over a column, then you also should label the resulting columns:

    # In case when you are using an expression, like "distinct" over a column, use "label" to preserve column names mapping
    result = session.execute(select(distinct(People.name).label("name"), People.height)).all()
    # here we have an iterator of "Row" objects
    for p in result:
        print(p.name, p.height)