You definitely can do that as long as you can define what is the "summable" column. Maybe you could do it by just data type of the column or by some naming convention.
In any event, below is the snippet of the code using simple column list from each table to achieve that.
Models:
# define actual ORM classes, but the code uses actual core `Table`
class Model1(Base):
__tablename__ = 'table1'
id = sa.Column(sa.Integer, primary_key=True)
column1 = sa.Column(sa.String)
column2 = sa.Column(sa.Numeric)
column3 = sa.Column(sa.Numeric)
class Model2(Base):
__tablename__ = 'table2'
id = sa.Column(sa.Integer, primary_key=True)
columnA = sa.Column(sa.String)
columnB = sa.Column(sa.Numeric)
columnC = sa.Column(sa.Numeric)
columnD = sa.Column(sa.Numeric)
Table1 = Model1.__table__
Table2 = Model2.__table__
Base query:
q = (
session.query(
Table1.c.column1,
Table2.c.columnA, # WHY need this when it is identical to `column1`?
)
.join(Table2, Table1.c.column1 == Table2.c.columnA)
.group_by(
Table1.c.column1,
Table2.c.columnB,
)
.order_by(
Table1.c.column1,
)
)
Additional columns:
summable_columns = {
Table1: [
'column2',
'column3',
],
Table2: [
'columnC',
'columnD',
],
}
for table, column_names in summable_columns.items():
for column_name in column_names:
column = getattr(getattr(table, 'c'), column_name)
label = 'sum_{table_name}_{column_name}'.format(table_name=table.name, column_name=column_name)
q = q.add_column(sa.func.sum(column).label(label))
for r in q:
print(r)
Additional columns (alternative):
Of course, you can define some other logic to extend the query. Example below does it with the type and exclude list (which hopefully is much smaller that the include version):
def is_summable(column):
exclude_columns = [
'id',
'column1',
'columnA',
'columnB',
]
return (
isinstance(column.type, (sa.Numeric, sa.Float, sa.Integer))
and column.name not in exclude_columns
)
for table in (Table1, Table2):
for column in getattr(table, 'c'):
label = 'sum_{table_name}_{column_name}'.format(table_name=table.name, column_name=column.name)
q = q.add_column(sa.func.sum(column).label(label))